#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
#include <sys/cmn_err.h>
#include <sys/modctl.h>
#include <sys/kobj.h>
#include <sys/kobj_impl.h>
#include <sys/promif.h>
#include <sys/promimpl.h>
#include <sys/reboot.h>
#include <sys/bootconf.h>
#include <sys/systm.h>
#include <sys/machsystm.h>
#define FDEBUGFILE "misc/forthdebug"
#define INSTALL_DBP "kdbg-words dbp-install previous"
#define SYMBOL_END "END OF SYMBOL"
#ifdef DEBUG
static int forthdebug = 1;
#else
static int forthdebug = 0;
#endif
static int forthdebug_dbp = 0;
int forthdebug_supported = 1;
int modreloc_flag = KOBJ_RELOCATED;
static char *basic_sym[] = {
"modules", "modules-val-here",
"primaries", "primaries-v-here",
"modreloc_flag", "modreloc-flagval",
0, 0
};
static void fdbp_hook() {}
static void fdbp_snoop(unsigned int i, struct modctl *modctl_p)
{
promif_preprom();
fdbp_hook();
promif_postprom();
}
static kobj_notify_list_t knl_load = {
fdbp_snoop, KOBJ_NOTIFY_MODLOADED, 0, 0
};
static kobj_notify_list_t knl_unload = {
fdbp_snoop, KOBJ_NOTIFY_MODUNLOADING, 0, 0
};
void
forthdebug_init(void)
{
char *fth_buf, *buf_p;
ulong_t modsym;
int i, sz;
uint64_t fsz;
struct _buf *file;
if (!forthdebug_supported) {
(void) modload("misc", "obpsym");
return;
}
forthdebug_dbp |= boothowto & RB_FORTHDEBUGDBP;
forthdebug |= (boothowto & RB_FORTHDEBUG) | forthdebug_dbp;
file = kobj_open_path(FDEBUGFILE, 1, 1);
if (file == (struct _buf *)-1) {
cmn_err(CE_CONT, "Can't open %s\n", FDEBUGFILE);
return;
}
i = kobj_get_filesize(file, &fsz);
if (i || !fsz) {
cmn_err(CE_CONT, "Can't stat %s stat=%x sz=%llx\n",
FDEBUGFILE, i, (long long)fsz);
goto err_stat;
}
fth_buf = (char *)kobj_zalloc(fsz + 1, KM_SLEEP);
sz = kobj_read_file(file, fth_buf, fsz, 0);
if (sz < 0) {
cmn_err(CE_CONT, "Error(%d) reading %s\n", sz, FDEBUGFILE);
goto done;
}
ASSERT(fsz == sz);
fth_buf[sz] = 0;
for (i = 0; basic_sym[i]; i += 2) {
buf_p = strstr(fth_buf, basic_sym[i + 1]);
modsym = kobj_getsymvalue(basic_sym[i], 0);
if (buf_p && modsym) {
(void) sprintf(buf_p, "%16p", (void *)modsym);
buf_p += 16;
*buf_p++ = ' ';
} else {
cmn_err(CE_CONT,
"forthdebug_init: No %s symbol(%p,%p), aborted\n",
basic_sym[i], (void *)buf_p, (void *)modsym);
goto done;
}
}
if (!forthdebug) {
if (!(buf_p = strstr(fth_buf, SYMBOL_END))) {
cmn_err(CE_CONT, "No %s in forthdebug\n", SYMBOL_END);
goto done;
}
*buf_p = '\0';
#ifdef DEBUG
cmn_err(CE_CONT, "symbol lookup service (%ld bytes)\n",
(long)(buf_p - fth_buf));
#endif
prom_interpret(fth_buf, 0, 0, 0, 0, 0);
goto done;
}
cmn_err(CE_CONT, "%s (%d bytes) ", FDEBUGFILE, sz);
prom_interpret(fth_buf, 0, 0, 0, 0, 0);
cmn_err(CE_CONT, "loaded\n");
obpdebug = 1;
if (forthdebug_dbp) {
#ifdef NO_KOBJ_NOTIFY
modsym = kobj_getsymvalue("kobj_notify_add", 0);
(void) ((int (*)(kobj_notify_list_t *))modsym)(&knl_load);
(void) ((int (*)(kobj_notify_list_t *))modsym)(&knl_unload);
#else
(void) kobj_notify_add(&knl_load);
(void) kobj_notify_add(&knl_unload);
#endif
prom_interpret(INSTALL_DBP, 0, 0, 0, 0, 0);
debug_enter("Defer breakpoint enabled. Add breakpoints, then");
}
done:
kobj_free(fth_buf, fsz + 1);
err_stat:
kobj_close_file(file);
if (boothowto & RB_HALT)
debug_enter("forthdebug: halt flag (-h) is set.\n");
}