code:
/*	$OpenBSD: db_run.c,v 1.25 2015/03/14 03:38:46 jsg Exp $	*/
/*	$NetBSD: db_run.c,v 1.8 1996/02/05 01:57:12 christos Exp $	*/

/*
 * Mach Operating System
 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 *
 * 	Author: David B. Golub, Carnegie Mellon University
 *	Date:	7/90
 */

/*
 * Commands to run process.
 */
#include <sys/param.h>
#include <sys/systm.h>

#include <machine/db_machdep.h>

#include <ddb/db_run.h>
#include <ddb/db_break.h>
#include <ddb/db_access.h>

#ifdef SOFTWARE_SSTEP
db_breakpoint_t	db_not_taken_bkpt = 0;
db_breakpoint_t	db_taken_bkpt = 0;
#endif

int		db_inst_count;

#ifndef KGDB

#include <ddb/db_watch.h>
#include <ddb/db_output.h>
#include <ddb/db_sym.h>
#include <ddb/db_extern.h>

int	db_run_mode;
#define	STEP_NONE	0
#define	STEP_ONCE	1
#define	STEP_RETURN	2
#define	STEP_CALLT	3
#define	STEP_CONTINUE	4
#define STEP_INVISIBLE	5
#define	STEP_COUNT	6

boolean_t	db_sstep_print;
int		db_loop_count;
int		db_call_depth;

boolean_t
db_stop_at_pc(db_regs_t *regs, boolean_t *is_breakpoint)
{
	db_addr_t	pc, old_pc;
	db_breakpoint_t	bkpt;

	db_clear_breakpoints();
	db_clear_watchpoints();
	old_pc = pc = PC_REGS(regs);

#ifdef	FIXUP_PC_AFTER_BREAK
	if (*is_breakpoint) {
		/*
		 * Breakpoint trap.  Fix up the PC if the
		 * machine requires it.
		 */
		FIXUP_PC_AFTER_BREAK(regs);
		pc = PC_REGS(regs);
	}
#endif

	/*
	 * Now check for a breakpoint at this address.
	 */
	bkpt = db_find_breakpoint(pc);
	if (bkpt) {
		if (--bkpt->count == 0) {
			db_clear_single_step(regs);
			bkpt->count = bkpt->init_count;
			*is_breakpoint = TRUE;
			return (TRUE);	/* stop here */
		}
	} else if (*is_breakpoint
#ifdef SOFTWARE_SSTEP
	    && !((db_taken_bkpt && db_taken_bkpt->address == pc) ||
	    (db_not_taken_bkpt && db_not_taken_bkpt->address == pc))
#endif
	    ) {
#ifdef PC_ADVANCE
		PC_ADVANCE(regs);
#else
# ifdef SET_PC_REGS
		SET_PC_REGS(regs, old_pc);
# else
		PC_REGS(regs) = old_pc;
# endif
#endif
	}
	db_clear_single_step(regs);

	*is_breakpoint = FALSE;

	if (db_run_mode == STEP_INVISIBLE) {
		db_run_mode = STEP_CONTINUE;
		return (FALSE);	/* continue */
	}
	if (db_run_mode == STEP_COUNT) {
		return (FALSE); /* continue */
	}
	if (db_run_mode == STEP_ONCE) {
		if (--db_loop_count > 0) {
			if (db_sstep_print) {
				db_printf("\t\t");
				db_print_loc_and_inst(pc);
				db_printf("\n");
			}
			return (FALSE);	/* continue */
		}
	}
	if (db_run_mode == STEP_RETURN) {
	    db_expr_t ins = db_get_value(pc, sizeof(int), FALSE);

	    /* continue until matching return */

	    if (!inst_trap_return(ins) &&
		(!inst_return(ins) || --db_call_depth != 0)) {
		if (db_sstep_print) {
		    if (inst_call(ins) || inst_return(ins)) {
			int i;

			db_printf("[after %6d]     ", db_inst_count);
			for (i = db_call_depth; --i > 0; )
			    db_printf("  ");
			db_print_loc_and_inst(pc);
			db_printf("\n");
		    }
		}
		if (inst_call(ins))
		    db_call_depth++;
		return (FALSE);	/* continue */
	    }
	}
	if (db_run_mode == STEP_CALLT) {
	    db_expr_t ins = db_get_value(pc, sizeof(int), FALSE);

	    /* continue until call or return */

	    if (!inst_call(ins) && !inst_return(ins) &&
		!inst_trap_return(ins)) {
		return (FALSE);	/* continue */
	    }
	}
	db_run_mode = STEP_NONE;
	return (TRUE);
}

void
db_restart_at_pc(db_regs_t *regs, boolean_t watchpt)
{
	db_addr_t pc = PC_REGS(regs);

	if ((db_run_mode == STEP_COUNT) || (db_run_mode == STEP_RETURN) ||
	    (db_run_mode == STEP_CALLT)) {
		db_expr_t	ins;

		/*
		 * We are about to execute this instruction,
		 * so count it now.
		 */
		ins = db_get_value(pc, sizeof(int), FALSE);
		db_inst_count++;
#ifdef	SOFTWARE_SSTEP
		/* XXX works on mips, but... */
		if (inst_branch(ins) || inst_call(ins)) {
			ins = db_get_value(next_instr_address(pc, 1),
			    sizeof(int), FALSE);
			db_inst_count++;
		}
#endif	/* SOFTWARE_SSTEP */
	}

	if (db_run_mode == STEP_CONTINUE) {
		if (watchpt || db_find_breakpoint(pc)) {
			/*
			 * Step over breakpoint/watchpoint.
			 */
			db_run_mode = STEP_INVISIBLE;
			db_set_single_step(regs);
		} else {
			db_set_breakpoints();
			db_set_watchpoints();
		}
	} else {
		db_set_single_step(regs);
	}
}

void
db_single_step(db_regs_t *regs)
{
	if (db_run_mode == STEP_CONTINUE) {
	    db_run_mode = STEP_INVISIBLE;
	    db_set_single_step(regs);
	}
}

/* single-step */
/*ARGSUSED*/
void
db_single_step_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
	boolean_t	print = FALSE;

	if (count == -1)
	    count = 1;

	if (modif[0] == 'p')
	    print = TRUE;

	db_run_mode = STEP_ONCE;
	db_loop_count = count;
	db_sstep_print = print;
	db_inst_count = 0;

	db_cmd_loop_done = 1;
}

/* trace and print until call/return */
/*ARGSUSED*/
void
db_trace_until_call_cmd(db_expr_t addr, int have_addr, db_expr_t count,
    char *modif)
{
	boolean_t	print = FALSE;

	if (modif[0] == 'p')
	    print = TRUE;

	db_run_mode = STEP_CALLT;
	db_sstep_print = print;
	db_inst_count = 0;

	db_cmd_loop_done = 1;
}

/*ARGSUSED*/
void
db_trace_until_matching_cmd(db_expr_t addr, int have_addr, db_expr_t count,
    char *modif)
{
	boolean_t	print = FALSE;

	if (modif[0] == 'p')
	    print = TRUE;

	db_run_mode = STEP_RETURN;
	db_call_depth = 1;
	db_sstep_print = print;
	db_inst_count = 0;

	db_cmd_loop_done = 1;
}

/* continue */
/*ARGSUSED*/
void
db_continue_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
	if (modif[0] == 'c')
	    db_run_mode = STEP_COUNT;
	else
	    db_run_mode = STEP_CONTINUE;
	db_inst_count = 0;

	db_cmd_loop_done = 1;
}
#endif /* NO KGDB */

#ifdef	SOFTWARE_SSTEP
/*
 *	Software implementation of single-stepping.
 *	If your machine does not have a trace mode
 *	similar to the vax or sun ones you can use
 *	this implementation, done for the mips.
 *	Just define the above conditional and provide
 *	the functions/macros defined below.
 *
 * extern boolean_t
 *	inst_branch(ins),	returns true if the instruction might branch
 * extern unsigned
 *	branch_taken(ins, pc, getreg_val, regs),
 *				return the address the instruction might
 *				branch to
 *	getreg_val(regs, reg),	return the value of a user register,
 *				as indicated in the hardware instruction
 *				encoding, e.g. 8 for r8
 *
 * next_instr_address(pc, bd)	returns the address of the first
 *				instruction following the one at "pc",
 *				which is either in the taken path of
 *				the branch (bd==1) or not.  This is
 *				for machines (mips) with branch delays.
 *
 *	A single-step may involve at most 2 breakpoints -
 *	one for branch-not-taken and one for branch taken.
 *	If one of these addresses does not already have a breakpoint,
 *	we allocate a breakpoint and save it here.
 *	These breakpoints are deleted on return.
 */

void
db_set_single_step(db_regs_t *regs)
{
	db_addr_t pc = PC_REGS(regs);
#ifndef SOFTWARE_SSTEP_EMUL
	db_addr_t brpc;
	u_int inst;

	/*
	 * User was stopped at pc, e.g. the instruction
	 * at pc was not executed.
	 */
	inst = db_get_value(pc, sizeof(int), FALSE);
	if (inst_branch(inst) || inst_call(inst) || inst_return(inst)) {
	    brpc = branch_taken(inst, pc, getreg_val, regs);
	    if (brpc != pc) {	/* self-branches are hopeless */
		db_taken_bkpt = db_set_temp_breakpoint(brpc);
	    }
#if 0
	    /* XXX this seems like a true bug, no?  */
	    pc = next_instr_address(pc, 1);
#endif
	}
#endif /*SOFTWARE_SSTEP_EMUL*/
	pc = next_instr_address(pc, 0);
	db_not_taken_bkpt = db_set_temp_breakpoint(pc);
}

void
db_clear_single_step(db_regs_t *regs)
{
	if (db_taken_bkpt != 0) {
	    db_delete_temp_breakpoint(db_taken_bkpt);
	    db_taken_bkpt = 0;
	}
	if (db_not_taken_bkpt != 0) {
	    db_delete_temp_breakpoint(db_not_taken_bkpt);
	    db_not_taken_bkpt = 0;
	}
}

#endif	/* SOFTWARE_SSTEP */


code:
/*	$OpenBSD: db_run.h,v 1.10 2010/11/27 19:57:23 miod Exp $	*/
/*	$NetBSD: db_run.h,v 1.3 1996/02/05 01:57:14 christos Exp $	*/

/*
 * Mach Operating System
 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 *
 * 	Author: David B. Golub, Carnegie Mellon University
 *	Date:	7/90
 */

#ifndef	_DDB_DB_RUN_
#define	_DDB_DB_RUN_

/*
 * Commands to run process.
 */
extern	int db_inst_count;
extern	int db_cmd_loop_done;

boolean_t db_stop_at_pc(db_regs_t *, boolean_t *);
void db_restart_at_pc(db_regs_t *, boolean_t);
void db_single_step(db_regs_t *);
#ifndef db_set_single_step
void db_set_single_step(db_regs_t *);
#endif
#ifndef db_clear_single_step
void db_clear_single_step(db_regs_t *);
#endif
void db_single_step_cmd(db_expr_t, int, db_expr_t, char *);
void db_trace_until_call_cmd(db_expr_t, int, db_expr_t, char *);
void db_trace_until_matching_cmd(db_expr_t, int, db_expr_t, char *);
void db_continue_cmd(db_expr_t, int, db_expr_t, char *);

#ifdef SOFTWARE_SSTEP
/*
 * I've seen this defined to (0) when it is not needed and then the proto will
 * not be correct, so skip it then.
 */
#ifndef getreg_val
extern register_t getreg_val(db_regs_t *, int);
#endif
#endif /* SOFTWARE_SSTEP */

#endif	/* _DDB_DB_RUN_ */

license: unknown


code:
/*	$OpenBSD: db_struct.c,v 1.3 2013/10/19 21:02:50 guenther Exp $	*/

/*
 * Copyright (c) 2009 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * ddb routines to describe struct information
 */

#include <sys/param.h>
#include <sys/systm.h>

#include <machine/db_machdep.h>

#include <ddb/db_lex.h>
#include <ddb/db_output.h>
#include <ddb/db_access.h>
#include <ddb/db_command.h>
#include <ddb/db_extern.h>
#include <ddb/db_interface.h>
#include <ddb/db_var.h>

#include "db_structinfo.h"

void	db_struct_print_field(uint, int, db_expr_t);

/*
 * Flags to pass db_struct_printf().
 */

#define	DBSP_STRUCT_NAME	0x01	/* prepend struct name */
#define	DBSP_VALUE		0x02	/* display field value */

void
db_struct_print_field(uint fidx, int flags, db_expr_t baseaddr)
{
	const struct ddb_field_info *field;
	const struct ddb_struct_info *struc;
	db_expr_t value;
	uint tmp;
	size_t namelen;
	int width, basecol, curcol;
	char tmpfmt[28];

	field = &ddb_field_info[fidx];
	basecol = 0;

	if (ISSET(flags, DBSP_STRUCT_NAME)) {
		struc = &ddb_struct_info[field->sidx];
		namelen = strlen(ddb_structfield_strings + struc->name);
		db_printf("%-30s ", ddb_structfield_strings + struc->name);
		if (namelen > 30)
			basecol += namelen + 1;
		else
			basecol += 30 + 1;
	}

	namelen = strlen(ddb_structfield_strings + field->name);
	if (field->nitems == 1) {
		db_printf("%-30s ", ddb_structfield_strings + field->name);
		if (namelen > 30)
			basecol += namelen + 1;
		else
			basecol += 30 + 1;
	} else {
		width = 30 - 2;
		tmp = field->nitems;
		while (tmp != 0) {
			width--;
			tmp /= 10;
		}
		if (namelen >= width) {
			db_printf("%s[%hu] ",
			    ddb_structfield_strings + field->name,
			    field->nitems);
			basecol += namelen + (30 - width) + 1;
		} else {
			db_printf("%s[%hu]%*s ",
			    ddb_structfield_strings + field->name,
			    field->nitems, width - (int)namelen, "");
			/* namelen + (30-width) + (width-namelen) + 1 */
			basecol += 30 + 1;
		}
	}

	if (field->size == 0) {
		db_printf("bitfield");
		/* basecol irrelevant from there on */
	} else {
		snprintf(tmpfmt, sizeof tmpfmt, "%u", (u_int)field->size);
		basecol += strlen(tmpfmt) + 1;
		db_printf("%s ", tmpfmt);
	}

	if (ISSET(flags, DBSP_VALUE)) {
		/* only print the field value if it has a friendly size. */
		switch (field->size) {
		case 1:
			width = 4;
			break;
		case 2:
			width = 8;
			break;
		case 4:
			width = 12;
			break;
#ifdef __LP64__
		case 8:
			width = 20;
			break;
#endif
		default:
			width = 0;
		}
		if (width != 0) {
			baseaddr += field->offs;
			curcol = basecol;
			for (tmp = field->nitems; tmp != 0; tmp--) {
				value = db_get_value(baseaddr, field->size,
				    FALSE); /* assume unsigned */
				db_format(tmpfmt, sizeof tmpfmt, (long)value,
				    DB_FORMAT_N, 0, width);
				if (field->nitems > 1)
					db_printf("%s", tmpfmt);
				else
					db_printf("%20s", tmpfmt);
				baseaddr += field->size;

				/*
				 * Try to fit array elements on as few lines
				 * as possible.
				 */
				if (field->nitems > 1 && tmp > 1) {
					curcol += width + 1;
					if (basecol >= db_max_width ||
					    curcol + width >= db_max_width) {
						/* new line */
						db_printf("\n");
						if (basecol + width >=
						    db_max_width) {
							db_printf("\t");
							curcol = 8;
						} else {
							db_printf("%*s",
							    basecol, "");
							curcol = basecol;
						}
					} else
						db_printf(" ");
				}
			}
		}
	}

	db_printf("\n");
}

/*
 * show offset <value>: displays the list of struct fields which exist
 * at that particular offset from the beginning of the struct.
 */
void
db_struct_offset_cmd(db_expr_t addr, int have_addr, db_expr_t count,
    char *modifiers)
{
	db_expr_t offset = 0;
	const struct ddb_field_offsets *field;
	const ddb_field_off *fidx;
	uint oidx;
	int width;
	char tmpfmt[28];

	/*
	 * Read the offset from the debuggger input.
	 * We don't want to get it from the standard parsing code, because
	 * this would set `dot' to this value, which doesn't make sense.
	 */

	if (!db_expression(&offset) || offset < 0) {
		db_printf("not a valid offset\n");
		db_flush_lex();
		return;
	}

	db_skip_to_eol();

	for (field = ddb_field_offsets, oidx = 0; oidx < NOFFS; field++, oidx++)
		if (field->offs == (size_t)offset)
			break;

	if (oidx == NOFFS) {
		db_format(tmpfmt, sizeof tmpfmt, (long)offset,
		    DB_FORMAT_N, 0, width);
		db_printf("no known structure element at offset %-*s\n",
		    width, tmpfmt);
		db_flush_lex();
		return;
	}

	db_printf("%-30s %-30s size\n", "struct", "member");
	for (fidx = ddb_fields_by_offset + field->list; *fidx != 0; fidx++)
		db_struct_print_field(*fidx, DBSP_STRUCT_NAME, 0);
}

/*
 * show struct <struct name> [addr]: displays the data starting at addr
 * (`dot' if unspecified) as a struct of the given type.
 */
void
db_struct_layout_cmd(db_expr_t addr, int have_addr, db_expr_t count,
    char *modifiers)
{
	const struct ddb_struct_info *struc;
	uint sidx, fidx;
	int t;

	/*
	 * Read the struct name from the debugger input.
	 */

	t = db_read_token();
	if (t != tIDENT) {
		db_printf("Bad struct name\n");
		db_flush_lex();
		return;
	}

	for (struc = ddb_struct_info, sidx = 0; sidx < NSTRUCT;
	    struc++, sidx++)
		if (strcmp(ddb_structfield_strings + struc->name,
		    db_tok_string) == 0)
			break;

	if (sidx == NSTRUCT) {
		db_printf("unknown struct %s\n", db_tok_string);
		db_flush_lex();
		return;
	}

	/*
	 * Read the address, if any, from the debugger input.
	 * In that case, update `dot' value.
	 */

	if (db_expression(&addr)) {
		db_dot = (db_addr_t)addr;
		db_last_addr = db_dot;
	} else
		addr = (db_expr_t)db_dot;

	db_skip_to_eol();

	/*
	 * Display the structure contents.
	 */

	db_printf("struct %s at %p (%u bytes)\n",
	    ddb_structfield_strings + struc->name, (void *)addr,
	    (u_int)struc->size);
	for (fidx = struc->fmin; fidx <= struc->fmax; fidx++)
		db_struct_print_field(fidx, DBSP_VALUE, addr);
}


code:
/* $OpenBSD: db_structinfo.c,v 1.13 2015/05/05 02:13:46 guenther Exp $ */
/* public domain */
/*
 * This file is intended to be compiled with debug information,
 * which is then translated by parse_debug.awk into support data
 * for ddb.
 */

#include <sys/param.h>
#include <sys/systm.h>

#include <sys/device.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/acct.h>
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/disk.h>
#include <sys/disklabel.h>
#include <sys/dirent.h>
#include <sys/dkbad.h>
#include <sys/evcount.h>
#include <sys/event.h>
#include <sys/eventvar.h>
#include <sys/exec.h>
#include <sys/extent.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/gpio.h>
#include <sys/hotplug.h>
#include <sys/ipc.h>
#include <sys/kcore.h>
#include <sys/kthread.h>
#include <sys/ktrace.h>
#include <sys/localedef.h>
#include <sys/lock.h>
#include <sys/lockf.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/memrange.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/msg.h>
#include <sys/msgbuf.h>
#include <sys/namei.h>
#include <sys/pipe.h>
#include <sys/pool.h>
#include <sys/protosw.h>
#include <sys/ptrace.h>
#include <sys/queue.h>
#include <sys/resource.h>
#include <sys/resourcevar.h>
#include <sys/rwlock.h>
#include <sys/sched.h>
#include <sys/select.h>
#include <sys/selinfo.h>
#include <sys/sem.h>
#include <sys/sensors.h>
#include <sys/shm.h>
#include <sys/siginfo.h>
#include <sys/signal.h>
#include <sys/signalvar.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/swap.h>
#include <sys/syscall.h>
#include <sys/syscallargs.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/termios.h>
#include <sys/time.h>
#include <sys/timeout.h>
#include <sys/timetc.h>
#include <sys/tprintf.h>
#include <sys/tree.h>
#include <sys/tty.h>
#include <sys/ucred.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <sys/unpcb.h>
#include <sys/utsname.h>
#include <sys/vmmeter.h>
#include <sys/vnode.h>
#include <sys/wait.h>

#include <machine/cpu.h>
#include <machine/conf.h>
#include <machine/mutex.h>

#include <uvm/uvm.h>

/* XXX add filesystem includes there */

#include <sys/ataio.h>
#include <sys/audioio.h>
#include <sys/cdio.h>
#include <sys/chio.h>
#include <sys/dkio.h>
#include <sys/filio.h>
#include <sys/mtio.h>
#include <sys/pciio.h>
#include <sys/radioio.h>
#include <sys/scanio.h>
#include <sys/scsiio.h>
#include <sys/sockio.h>
#include <sys/videoio.h>


code:
/*	$OpenBSD: db_sym.c,v 1.37 2015/03/14 03:38:46 jsg Exp $	*/
/*	$NetBSD: db_sym.c,v 1.24 2000/08/11 22:50:47 tv Exp $	*/

/*
 * Mach Operating System
 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */

#include <sys/param.h>
#include <sys/systm.h>

#include <machine/db_machdep.h>

#include <ddb/db_lex.h>
#include <ddb/db_sym.h>
#include <ddb/db_output.h>
#include <ddb/db_command.h>

/*
 * Multiple symbol tables
 */
#ifndef MAXLKMS
#define MAXLKMS 20
#endif

#ifndef MAXNOSYMTABS
#define	MAXNOSYMTABS	MAXLKMS+1	/* Room for kernel + LKM's */
#endif

db_symtab_t	db_symtabs[MAXNOSYMTABS] = {{0,},};

db_symtab_t	*db_last_symtab;

static db_forall_func_t db_sift;

extern char end[];

/*
 * Put the most picky symbol table formats at the top!
 */
const db_symformat_t *db_symformats[] = {
	&db_symformat_elf,
	NULL,
};

const db_symformat_t *db_symformat;

boolean_t	X_db_sym_init(int, void *, void *, const char *);
db_sym_t	X_db_lookup(db_symtab_t *, char *);
db_sym_t	X_db_search_symbol(db_symtab_t *, db_addr_t,
		    db_strategy_t, db_expr_t *);
void		X_db_symbol_values(db_symtab_t *, db_sym_t, char **,
		    db_expr_t *);
boolean_t	X_db_line_at_pc(db_symtab_t *, db_sym_t, char **,
		    int *, db_expr_t);
int		X_db_sym_numargs(db_symtab_t *, db_sym_t, int *,
		    char **);

/*
 * Initialize the kernel debugger by initializing the master symbol
 * table.  Note that if initializing the master symbol table fails,
 * no other symbol tables can be loaded.
 */
#if 0
void
ddb_init(int symsize, void *vss, void *vse)
{
	const db_symformat_t **symf;
	const char *name = "bsd";

	if (symsize <= 0) {
		printf(" [ no symbols available ]\n");
		return;
	}

	/*
	 * Do this check now for the master symbol table to avoid printing
	 * the message N times.
	 */
	if (ALIGNED_POINTER(vss, long) == 0) {
		printf("[ %s symbol table has bad start address %p ]\n",
		    name, vss);
		return;
	}

	for (symf = db_symformats; *symf != NULL; symf++) {
		db_symformat = *symf;
		if (X_db_sym_init(symsize, vss, vse, name) == TRUE)
			return;
	}

	db_symformat = NULL;
	printf("[ no symbol table formats found ]\n");
}
#else
void
ddb_init(void)
{
	const db_symformat_t **symf;
	const char *name = "bsd";
	extern char *esym;
#if defined(__sparc64__) || defined(__mips__) || defined(__amd64__)
	extern char *ssym;
#endif
	char *xssym, *xesym;

	xesym = esym;
#if defined(__sparc64__) || defined(__mips__) || defined(__amd64__)
	xssym = ssym;
#else
	xssym = (char *)&end;
#endif
	/*
	 * Do this check now for the master symbol table to avoid printing
	 * the message N times.
	 */
	if ((((vaddr_t)xssym) & (sizeof(long) - 1)) != 0) {
		printf("[ %s symbol table has bad start address %p ]\n",
		    name, xssym);
		return;
	}

	if (xesym != NULL && xesym != xssym)
		for (symf = db_symformats; *symf != NULL; symf++) {
			db_symformat = *symf;
			if (X_db_sym_init((vaddr_t)xesym - (vaddr_t)xssym,
			    xssym, xesym, name) == TRUE)
			return;
		}

	db_symformat = NULL;
	printf("[ no symbol table formats found ]\n");
}
#endif

/*
 * Add symbol table, with given name, to list of symbol tables.
 */
int
db_add_symbol_table(char *start, char *end, const char *name, char *ref)
{
	int slot;

	for (slot = 0; slot < MAXNOSYMTABS; slot++) {
		if (db_symtabs[slot].name == NULL)
			break;
	}
	if (slot >= MAXNOSYMTABS) {
		db_printf("No slots left for %s symbol table", name);
		return(-1);
	}

	db_symtabs[slot].start = start;
	db_symtabs[slot].end = end;
	db_symtabs[slot].name = name;
	db_symtabs[slot].private = ref;

	return(slot);
}

/*
 * Delete a symbol table. Caller is responsible for freeing storage.
 */
void
db_del_symbol_table(char *name)
{
	int slot;

	for (slot = 0; slot < MAXNOSYMTABS; slot++) {
		if (db_symtabs[slot].name &&
		    ! strcmp(db_symtabs[slot].name, name))
			break;
	}
	if (slot >= MAXNOSYMTABS) {
		db_printf("Unable to find symbol table slot for %s.", name);
		return;
	}

	db_symtabs[slot].start = 0;
	db_symtabs[slot].end = 0;
	db_symtabs[slot].name = 0;
	db_symtabs[slot].private = 0;
}

/*
 *  db_qualify("vm_map", "bsd") returns "bsd:vm_map".
 *
 *  Note: return value points to static data whose content is
 *  overwritten by each call... but in practice this seems okay.
 */
char *
db_qualify(db_sym_t sym, const char *symtabname)
{
	char		*symname;
	static char     tmp[256];
	char	*s;

	db_symbol_values(sym, &symname, 0);
	s = tmp;
	while ((*s++ = *symtabname++) != '\0')
		;
	s[-1] = ':';
	while ((*s++ = *symname++) != '\0')
		;
	return tmp;
}

boolean_t
db_eqname(char *src, char *dst, int c)
{
	if (!strcmp(src, dst))
	    return (TRUE);
	if (src[0] == c)
	    return (!strcmp(src+1,dst));
	return (FALSE);
}

boolean_t
db_value_of_name(char *name, db_expr_t *valuep)
{
	db_sym_t	sym;

	sym = db_lookup(name);
	if (sym == DB_SYM_NULL)
	    return (FALSE);
	db_symbol_values(sym, &name, valuep);
	return (TRUE);
}

/*
 * Lookup a symbol.
 * If the symbol has a qualifier (e.g., ux:vm_map),
 * then only the specified symbol table will be searched;
 * otherwise, all symbol tables will be searched.
 */
db_sym_t
db_lookup(char *symstr)
{
	db_sym_t sp;
	int i;
	int symtab_start = 0;
	int symtab_end = MAXNOSYMTABS;
	char *cp;

	/*
	 * Look for, remove, and remember any symbol table specifier.
	 */
	for (cp = symstr; *cp; cp++) {
		if (*cp == ':') {
			*cp = '\0';
			for (i = 0; i < MAXNOSYMTABS; i++) {
				if (db_symtabs[i].name &&
				    ! strcmp(symstr, db_symtabs[i].name)) {
					symtab_start = i;
					symtab_end = i + 1;
					break;
				}
			}
			*cp = ':';
			if (i == MAXNOSYMTABS) {
				db_error("invalid symbol table name");
				/*NOTREACHED*/
			}
			symstr = cp+1;
		}
	}

	/*
	 * Look in the specified set of symbol tables.
	 * Return on first match.
	 */
	for (i = symtab_start; i < symtab_end; i++) {
		if (db_symtabs[i].name &&
		    (sp = X_db_lookup(&db_symtabs[i], symstr))) {
			db_last_symtab = &db_symtabs[i];
			return sp;
		}
	}
	return 0;
}

/* Private structure for passing args to db_sift() from db_sifting(). */
struct db_sift_args {
	char	*symstr;
	int	mode;
};

/*
 * Does the work of db_sifting(), called once for each
 * symbol via X_db_forall(), prints out symbols matching
 * criteria.
 */
static void
db_sift(db_symtab_t *stab, db_sym_t sym, char *name, char *suffix, int prefix,
    void *arg)
{
	char c, sc;
	char *find, *p;
	size_t len;
	struct db_sift_args *dsa;

	dsa = (struct db_sift_args*)arg;

	find = dsa->symstr;	/* String we're looking for. */
	p = name;		/* String we're searching within. */

	/* Matching algorithm cribbed from strstr(), which is not
	   in the kernel. */
	if ((c = *find++) != 0) {
		len = strlen(find);
		do {
			do {
				if ((sc = *p++) == 0)
					return;
			} while (sc != c);
		} while (strncmp(p, find, len) != 0);
	}
	if (dsa->mode=='F')	/* ala ls -F */
		db_printf("%s%s ", name, suffix);
	else
		db_printf("%s ", name);
}

/*
 * "Sift" for a partial symbol.
 * Named for the Sun OpenPROM command ("sifting").
 * If the symbol has a qualifier (e.g., ux:vm_map),
 * then only the specified symbol table will be searched;
 * otherwise, all symbol tables will be searched..
 *
 * "mode" is how-to-display, set from modifiers.
 */
void
db_sifting(char *symstr, int mode)
{
	char *cp;
	int i;
	int symtab_start = 0;
	int symtab_end = MAXNOSYMTABS;
	struct db_sift_args dsa;

	/*
	 * Look for, remove, and remember any symbol table specifier.
	 */
	for (cp = symstr; *cp; cp++) {
		if (*cp == ':') {
			*cp = '\0';
			for (i = 0; i < MAXNOSYMTABS; i++) {
				if (db_symtabs[i].name &&
				    ! strcmp(symstr, db_symtabs[i].name)) {
					symtab_start = i;
					symtab_end = i + 1;
					break;
				}
			}
			*cp = ':';
			if (i == MAXNOSYMTABS) {
				db_error("invalid symbol table name");
				/*NOTREACHED*/
			}
			symstr = cp+1;
		}
	}

	/* Pass args to db_sift(). */
	dsa.symstr = symstr;
	dsa.mode = mode;

	/*
	 * Look in the specified set of symbol tables.
	 */
	for (i = symtab_start; i < symtab_end; i++)
		if (db_symtabs[i].name) {
			db_printf("Sifting table %s:\n", db_symtabs[i].name);
			X_db_forall(&db_symtabs[i], db_sift, &dsa);
		}

	return;
}

/*
 * Does this symbol name appear in more than one symbol table?
 * Used by db_symbol_values to decide whether to qualify a symbol.
 */
boolean_t db_qualify_ambiguous_names = FALSE;

boolean_t
db_symbol_is_ambiguous(db_sym_t sym)
{
	char		*sym_name;
	int	i;
	boolean_t	found_once = FALSE;

	if (!db_qualify_ambiguous_names)
		return FALSE;

	db_symbol_values(sym, &sym_name, 0);
	for (i = 0; i < MAXNOSYMTABS; i++) {
		if (db_symtabs[i].name &&
		    X_db_lookup(&db_symtabs[i], sym_name)) {
			if (found_once)
				return TRUE;
			found_once = TRUE;
		}
	}
	return FALSE;
}

/*
 * Find the closest symbol to val, and return its name
 * and the difference between val and the symbol found.
 */
db_sym_t
db_search_symbol(db_addr_t val, db_strategy_t strategy, db_expr_t *offp)
{
	unsigned int	diff;
	db_expr_t	newdiff;
	int		i;
	db_sym_t	ret = DB_SYM_NULL, sym;

	newdiff = diff = ~0;
	db_last_symtab = 0;
	for (i = 0; i < MAXNOSYMTABS; i++) {
	    if (!db_symtabs[i].name)
	        continue;
	    sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
	    if (newdiff < diff) {
		db_last_symtab = &db_symtabs[i];
		diff = newdiff;
		ret = sym;
	    }
	}
	*offp = diff;
	return ret;
}

/*
 * Return name and value of a symbol
 */
void
db_symbol_values(db_sym_t sym, char **namep, db_expr_t *valuep)
{
	db_expr_t	value;

	if (sym == DB_SYM_NULL) {
		*namep = 0;
		return;
	}

	X_db_symbol_values(db_last_symtab, sym, namep, &value);

	if (db_symbol_is_ambiguous(sym))
		*namep = db_qualify(sym, db_last_symtab->name);
	if (valuep)
		*valuep = value;
}

/*
 * Print a the closest symbol to value
 *
 * After matching the symbol according to the given strategy
 * we print it in the name+offset format, provided the symbol's
 * value is close enough (eg smaller than db_maxoff).
 * We also attempt to print [filename:linenum] when applicable
 * (eg for procedure names).
 *
 * If we could not find a reasonable name+offset representation,
 * then we just print the value in hex.  Small values might get
 * bogus symbol associations, e.g. 3 might get some absolute
 * value like _INCLUDE_VERSION or something, therefore we do
 * not accept symbols whose value is zero (and use plain hex).
 * Also, avoid printing as "end+0x????" which is useless.
 * The variable db_lastsym is used instead of "end" in case we
 * add support for symbols in loadable driver modules.
 */
unsigned long	db_lastsym = (unsigned long)end;
unsigned int	db_maxoff = 0x10000000;

void
db_printsym(db_expr_t off, db_strategy_t strategy,
    int (*pr)(const char *, ...))
{
	db_expr_t	d;
	char 		*filename;
	char		*name;
	db_expr_t	value;
	int 		linenum;
	db_sym_t	cursym;
	char		buf[DB_FORMAT_BUF_SIZE];

	if (off <= db_lastsym) {
		cursym = db_search_symbol(off, strategy, &d);
		db_symbol_values(cursym, &name, &value);
		if (name && (d < db_maxoff) && value) {
			(*pr)("%s", name);
			if (d) {
				(*pr)("+%s", db_format(buf, sizeof(buf),
				    d, DB_FORMAT_R, 1, 0));
			}
			if (strategy == DB_STGY_PROC) {
				if (db_line_at_pc(cursym, &filename, &linenum, off))
					(*pr)(" [%s:%d]", filename, linenum);
			}
			return;
		}
	}

	(*pr)("%s", db_format(buf, sizeof(buf), off, DB_FORMAT_N, 1, 0));
	return;
}

boolean_t
db_line_at_pc(db_sym_t sym, char **filename, int *linenum, db_expr_t pc)
{
	return X_db_line_at_pc(db_last_symtab, sym, filename, linenum, pc);
}

int
db_sym_numargs(db_sym_t sym, int *nargp, char **argnames)
{
	return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
}

boolean_t
X_db_sym_init(int symsize, void *vss, void *vse, const char *name)
{

	if (db_symformat != NULL)
		return ((*db_symformat->sym_init)(symsize, vss, vse, name));
	return (FALSE);
}

db_sym_t
X_db_lookup(db_symtab_t *stab, char *symstr)
{

	if (db_symformat != NULL)
		return ((*db_symformat->sym_lookup)(stab, symstr));
	return ((db_sym_t)0);
}

db_sym_t
X_db_search_symbol(db_symtab_t *stab, db_addr_t off, db_strategy_t strategy,
    db_expr_t *diffp)
{

	if (db_symformat != NULL)
		return ((*db_symformat->sym_search)(stab, off, strategy,
		    diffp));
	return ((db_sym_t)0);
}

void
X_db_symbol_values(db_symtab_t *stab, db_sym_t sym, char **namep,
    db_expr_t *valuep)
{

	if (db_symformat != NULL)
		(*db_symformat->sym_value)(stab, sym, namep, valuep);
}

boolean_t
X_db_line_at_pc(db_symtab_t *stab, db_sym_t cursym, char **filename,
    int *linenum, db_expr_t off)
{

	if (db_symformat != NULL)
		return ((*db_symformat->sym_line_at_pc)(stab, cursym,
		    filename, linenum, off));
	return (FALSE);
}

boolean_t
X_db_sym_numargs(db_symtab_t *stab, db_sym_t cursym, int *nargp,
    char **argnamep)
{

	if (db_symformat != NULL)
		return ((*db_symformat->sym_numargs)(stab, cursym, nargp,
		    argnamep));
	return (FALSE);
}

void
X_db_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg)
{
	if (db_symformat != NULL)
		(*db_symformat->sym_forall)(stab, db_forall_func, arg);
}


code:
/*	$NetBSD: db_sym.h,v 1.13 2000/05/25 19:57:36 jhawk Exp $	*/

/*
 * Mach Operating System
 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 *
 * 	Author: Alessandro Forin, Carnegie Mellon University
 *	Date:	8/90
 */

/*
 * This module can handle multiple symbol tables
 */
typedef struct {
	const char	*name;		/* symtab name */
	char		*start;		/* symtab location */
	char		*end;
	char		*private;	/* optional machdep pointer */
} db_symtab_t;

extern db_symtab_t	*db_last_symtab; /* where last symbol was found */

/*
 * Symbol representation is specific to the symtab style:
 * BSD compilers use dbx' nlist, other compilers might use
 * a different one
 */
typedef	char *		db_sym_t;	/* opaque handle on symbols */
#define	DB_SYM_NULL	((db_sym_t)0)

/*
 * Non-stripped symbol tables will have duplicates, for instance
 * the same string could match a parameter name, a local var, a
 * global var, etc.
 * We are most concern with the following matches.
 */
typedef int		db_strategy_t;	/* search strategy */

#define	DB_STGY_ANY	0			/* anything goes */
#define DB_STGY_XTRN	1			/* only external symbols */
#define DB_STGY_PROC	2			/* only procedures */

/*
 * Internal db_forall function calling convention:
 *
 * (*db_forall_func)(stab, sym, name, suffix, prefix, arg);
 *
 * stab is the symbol table, symbol the (opaque) symbol pointer,
 * name the name of the symbol, suffix a string representing
 * the type, prefix an initial ignorable function prefix (e.g. "_"
 * in a.out), and arg an opaque argument to be passed in.
 */
typedef void (db_forall_func_t)(db_symtab_t *, db_sym_t, char *, char *, int, void *);

void		X_db_forall(db_symtab_t *,
		    db_forall_func_t db_forall_func, void *);

/*
 * A symbol table may be in one of many formats.  All symbol tables
 * must be of the same format as the master kernel symbol table.
 */
typedef struct {
	const char *sym_format;
	boolean_t (*sym_init)(int, void *, void *, const char *);
	db_sym_t (*sym_lookup)(db_symtab_t *, char *);
	db_sym_t (*sym_search)(db_symtab_t *, db_addr_t, db_strategy_t,
		db_expr_t *);
	void	(*sym_value)(db_symtab_t *, db_sym_t, char **,
		db_expr_t *);
	boolean_t (*sym_line_at_pc)(db_symtab_t *, db_sym_t,
		char **, int *, db_expr_t);
	boolean_t (*sym_numargs)(db_symtab_t *, db_sym_t, int *,
		char **);
	void	(*sym_forall)(db_symtab_t *,
		db_forall_func_t *db_forall_func, void *);
} db_symformat_t;

extern boolean_t	db_qualify_ambiguous_names;
					/* if TRUE, check across symbol tables
					 * for multiple occurrences of a name.
					 * Might slow down quite a bit */

extern unsigned int db_maxoff;		/* like gdb's "max-symbolic-offset" */
/*
 * Functions exported by the symtable module
 */
int db_add_symbol_table(char *, char *, const char *, char *);
					/* extend the list of symbol tables */

void db_del_symbol_table(char *);
					/* remove a symbol table from list */

boolean_t db_eqname(char *, char *, int);
					/* strcmp, modulo leading char */

int db_value_of_name(char *, db_expr_t *);
					/* find symbol value given name */

db_sym_t db_lookup(char *);

void db_sifting(char *, int);
				/* print partially matching symbol names */

boolean_t db_symbol_is_ambiguous(db_sym_t);

db_sym_t db_search_symbol(db_addr_t, db_strategy_t, db_expr_t *);
					/* find symbol given value */

void db_symbol_values(db_sym_t, char **, db_expr_t *);
					/* return name and value of symbol */

#define db_find_sym_and_offset(val,namep,offp)	\
	db_symbol_values(db_search_symbol(val,DB_STGY_ANY,offp),namep,0)
					/* find name&value given approx val */

#define db_find_xtrn_sym_and_offset(val,namep,offp)	\
	db_symbol_values(db_search_symbol(val,DB_STGY_XTRN,offp),namep,0)
					/* ditto, but no locals */

void db_printsym(db_expr_t, db_strategy_t, int (*)(const char *, ...));
					/* print closest symbol to a value */

boolean_t db_line_at_pc(db_sym_t, char **, int *, db_expr_t);

int db_sym_numargs(db_sym_t, int *, char **);
char *db_qualify(db_sym_t, const char *);

extern	db_symformat_t db_symformat_elf;


code:
/*	$OpenBSD: db_trap.c,v 1.19 2015/03/14 03:38:46 jsg Exp $	*/
/*	$NetBSD: db_trap.c,v 1.9 1996/02/05 01:57:18 christos Exp $	*/

/*
 * Mach Operating System
 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 *
 * 	Author: David B. Golub, Carnegie Mellon University
 *	Date:	7/90
 */

/*
 * Trap entry point to kernel debugger.
 */
#include <sys/param.h>
#include <sys/systm.h>

#include <machine/db_machdep.h>

#include <ddb/db_run.h>
#include <ddb/db_command.h>
#include <ddb/db_output.h>
#include <ddb/db_sym.h>
#include <ddb/db_extern.h>
#include <ddb/db_interface.h>
#include <ddb/db_var.h>

void
db_trap(int type, int code)
{
	boolean_t	bkpt;
	boolean_t	watchpt;

	db_is_active = 1;
	bkpt = IS_BREAKPOINT_TRAP(type, code);
	watchpt = IS_WATCHPOINT_TRAP(type, code);

	if (db_stop_at_pc(DDB_REGS, &bkpt)) {
		if (db_inst_count) {
			db_printf("After %d instructions\n", db_inst_count);
		}
		if (bkpt)
			db_printf("Breakpoint at\t");
		else if (watchpt)
			db_printf("Watchpoint at\t");
		else
			db_printf("Stopped at\t");
		db_dot = PC_REGS(DDB_REGS);
		db_print_loc_and_inst(db_dot);

		/*
		 * Just in case we do not have any usable console driver,
		 * give the user a traceback.
		 */
		if (cold) {
			db_stack_trace_print(db_dot, 0, 10 /* arbitrary */, "",
			    db_printf);
		}

		if (panicstr != NULL) {
			if (db_print_position() != 0)
				db_printf("\n");
			db_printf("RUN AT LEAST 'trace' AND 'ps' AND INCLUDE "
			    "OUTPUT WHEN REPORTING THIS PANIC!\n");
#ifdef MULTIPROCESSOR
			db_printf("IF RUNNING SMP, USE 'mach ddbcpu <#>' AND "
			    "'trace' ON OTHER PROCESSORS, TOO.\n");
#endif
			db_printf("DO NOT EVEN BOTHER REPORTING THIS WITHOUT "
			    "INCLUDING THAT INFORMATION!\n");
		}

		db_command_loop();
	}

	db_restart_at_pc(DDB_REGS, watchpt);
	db_is_active = 0;
}


code:
/*	$OpenBSD: db_usrreq.c,v 1.17 2015/03/14 03:38:46 jsg Exp $	*/

/*
 * Copyright (c) 1996 Michael Shalayeff.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/tty.h>
#include <sys/sysctl.h>
#include <dev/cons.h>

#include <ddb/db_var.h>

int	db_log = 1;

int
ddb_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
    size_t newlen, struct proc *p)
{
	int error, ctlval;

	/* All sysctl names at this level are terminal. */
	if (namelen != 1)
		return (ENOTDIR);

	switch (name[0]) {

	case DBCTL_RADIX:
		return sysctl_int(oldp, oldlenp, newp, newlen, &db_radix);
	case DBCTL_MAXWIDTH:
		return sysctl_int(oldp, oldlenp, newp, newlen, &db_max_width);
	case DBCTL_TABSTOP:
		return sysctl_int(oldp, oldlenp, newp, newlen, &db_tab_stop_width);
	case DBCTL_MAXLINE:
		return sysctl_int(oldp, oldlenp, newp, newlen, &db_max_line);
	case DBCTL_PANIC:
		if (securelevel > 0)
			return (sysctl_int_lower(oldp, oldlenp, newp, newlen,
			    &db_panic));
		else {
			ctlval = db_panic;
			if ((error = sysctl_int(oldp, oldlenp, newp, newlen,
			    &ctlval)) || newp == NULL)
				return (error);
			if (ctlval != 1 && ctlval != 0)
				return (EINVAL);
			db_panic = ctlval;
			return (0);
		}
		break;
	case DBCTL_CONSOLE:
		if (securelevel > 0)
			return (sysctl_int_lower(oldp, oldlenp, newp, newlen,
			    &db_console));
		else {
			ctlval = db_console;
			if ((error = sysctl_int(oldp, oldlenp, newp, newlen,
			    &ctlval)) || newp == NULL)
				return (error);
			if (ctlval != 1 && ctlval != 0)
				return (EINVAL);
			db_console = ctlval;
			return (0);
		}
		break;
	case DBCTL_LOG:
		return (sysctl_int(oldp, oldlenp, newp, newlen, &db_log));
	case DBCTL_TRIGGER:
		if (newp && db_console) {
			struct process *pr = curproc->p_p;

			if (securelevel < 1 ||
			    (pr->ps_flags & PS_CONTROLT && cn_tab &&
			    cn_tab->cn_dev == pr->ps_session->s_ttyp->t_dev)) {
				Debugger();
				newp = NULL;
			} else
				return (ENODEV);
		}
		return (sysctl_rdint(oldp, oldlenp, newp, 0));
	default:
		return (EOPNOTSUPP);
	}
	/* NOTREACHED */
}


code:
/*	$OpenBSD: db_var.h,v 1.11 2011/04/03 16:46:19 drahn Exp $	*/

/*
 * Copyright (c) 1996 Michael Shalayeff.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Different parameters/structures/functions
 */

#ifndef _DDB_DB_VAR_H_
#define _DDB_DB_VAR_H_

#ifndef	DB_HISTORY_SIZE
#define	DB_HISTORY_SIZE	4000
#endif

#define DBCTL_RADIX	1
#define DBCTL_MAXWIDTH	2
#define DBCTL_MAXLINE	3
#define DBCTL_TABSTOP	4
#define DBCTL_PANIC	5
#define DBCTL_CONSOLE	6
#define DBCTL_LOG	7
#define DBCTL_TRIGGER	8
#define DBCTL_MAXID	9

#define	CTL_DDB_NAMES { \
	{ NULL, 0 }, \
	{ "radix", CTLTYPE_INT }, \
	{ "max_width", CTLTYPE_INT }, \
	{ "max_line", CTLTYPE_INT }, \
	{ "tab_stop_width", CTLTYPE_INT },\
	{ "panic", CTLTYPE_INT }, \
	{ "console", CTLTYPE_INT }, \
	{ "log", CTLTYPE_INT }, \
	{ "trigger", CTLTYPE_INT }, \
}

#ifdef	_KERNEL
extern int	db_radix;
extern int	db_max_width;
extern int	db_tab_stop_width;
extern int	db_max_line;
extern int	db_panic;
extern int	db_console;
extern int	db_log;
extern int	db_is_active;

int	ddb_sysctl(int *, u_int, void *, size_t *, void *, size_t,
		       struct proc *);
#endif

#endif /* _DDB_DB_VAR_H_ */


code:
/*	$OpenBSD: db_variables.c,v 1.17 2015/03/14 05:48:17 tedu Exp $	*/
/*	$NetBSD: db_variables.c,v 1.8 1996/02/05 01:57:19 christos Exp $	*/

/*
 * Mach Operating System
 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */

#include <sys/param.h>
#include <sys/systm.h>

#include <machine/db_machdep.h>

#include <ddb/db_lex.h>
#include <ddb/db_variables.h>
#include <ddb/db_command.h>
#include <ddb/db_sym.h>
#include <ddb/db_extern.h>
#include <ddb/db_var.h>

struct db_variable db_vars[] = {
	{ "radix",	(long *)&db_radix, db_var_rw_int },
	{ "maxoff",	(long *)&db_maxoff, db_var_rw_int },
	{ "maxwidth",	(long *)&db_max_width, db_var_rw_int },
	{ "tabstops",	(long *)&db_tab_stop_width, db_var_rw_int },
	{ "lines",	(long *)&db_max_line, db_var_rw_int },
	{ "log",	(long *)&db_log, db_var_rw_int }
};
struct db_variable *db_evars = db_vars + nitems(db_vars);

int
db_find_variable(struct db_variable **varp)
{
	int	t;
	struct db_variable *vp;

	t = db_read_token();
	if (t == tIDENT) {
	    for (vp = db_vars; vp < db_evars; vp++) {
		if (!strcmp(db_tok_string, vp->name)) {
		    *varp = vp;
		    return (1);
		}
	    }
	    for (vp = db_regs; vp < db_eregs; vp++) {
		if (!strcmp(db_tok_string, vp->name)) {
		    *varp = vp;
		    return (1);
		}
	    }
	}
	db_error("Unknown variable\n");
	/*NOTREACHED*/
	return 0;
}

int
db_get_variable(db_expr_t *valuep)
{
	struct db_variable *vp;

	if (!db_find_variable(&vp))
	    return (0);

	db_read_variable(vp, valuep);

	return (1);
}

int
db_set_variable(db_expr_t value)
{
	struct db_variable *vp;

	if (!db_find_variable(&vp))
	    return (0);

	db_write_variable(vp, &value);

	return (1);
}

void
db_read_variable(struct db_variable *vp, db_expr_t *valuep)
{
	int	(*func)(struct db_variable *, db_expr_t *, int) = vp->fcn;

	if (func == FCN_NULL)
	    *valuep = *(vp->valuep);
	else
	    (*func)(vp, valuep, DB_VAR_GET);
}

void
db_write_variable(struct db_variable *vp, db_expr_t *valuep)
{
	int	(*func)(struct db_variable *, db_expr_t *, int) = vp->fcn;

	if (func == FCN_NULL)
	    *(vp->valuep) = *valuep;
	else
	    (*func)(vp, valuep, DB_VAR_SET);
}

/*ARGSUSED*/
void
db_set_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
	db_expr_t	value;
	struct db_variable *vp;
	int	t;

	t = db_read_token();
	if (t != tDOLLAR) {
	    db_error("Unknown variable\n");
	    /*NOTREACHED*/
	}
	if (!db_find_variable(&vp)) {
	    db_error("Unknown variable\n");
	    /*NOTREACHED*/
	}

	t = db_read_token();
	if (t != tEQ)
	    db_unread_token(t);

	if (!db_expression(&value)) {
	    db_error("No value\n");
	    /*NOTREACHED*/
	}
	if (db_read_token() != tEOL) {
	    db_error("?\n");
	    /*NOTREACHED*/
	}

	db_write_variable(vp, &value);
}

int
db_var_rw_int(struct db_variable *var, db_expr_t *expr, int mode)
{

	if (mode == DB_VAR_SET)
		*var->valuep = *(int *)expr;
	else
		*expr = *(int *)var->valuep;
	return (0);
}


code:
/*	$OpenBSD: db_variables.h,v 1.7 2006/07/06 19:05:58 miod Exp $	*/
/*	$NetBSD: db_variables.h,v 1.5 1996/02/05 01:57:21 christos Exp $	*/

/*
 * Mach Operating System
 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 *
 * 	Author: David B. Golub, Carnegie Mellon University
 *	Date:	7/90
 */

#ifndef	_DB_VARIABLES_H_
#define	_DB_VARIABLES_H_

/*
 * Debugger variables.
 */
struct db_variable {
	char	*name;		/* Name of variable */
	long	*valuep;	/* value of variable */
				/* function to call when reading/writing */
	int	(*fcn)(struct db_variable *, db_expr_t *, int);
#define DB_VAR_GET	0
#define DB_VAR_SET	1
};
#define	FCN_NULL ((int (*)(struct db_variable *, db_expr_t *, int))0)

extern struct db_variable	db_vars[];	/* debugger variables */
extern struct db_variable	*db_evars;
extern struct db_variable	db_regs[];	/* machine registers */
extern struct db_variable	*db_eregs;

int	db_find_variable(struct db_variable **);
int	db_get_variable(db_expr_t *);
int	db_set_variable(db_expr_t);
void	db_read_variable(struct db_variable *, db_expr_t *);
void	db_write_variable(struct db_variable *, db_expr_t *);
void	db_set_cmd(db_expr_t, int, db_expr_t, char *);
int	db_var_rw_int(struct db_variable *, db_expr_t *, int);

#endif	/* _DB_VARIABLES_H_ */


code:
/*	$OpenBSD: db_watch.c,v 1.14 2015/03/14 03:38:46 jsg Exp $ */
/*	$NetBSD: db_watch.c,v 1.9 1996/03/30 22:30:12 christos Exp $	*/

/*
 * Mach Operating System
 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 *
 * 	Author: Richard P. Draves, Carnegie Mellon University
 *	Date:	10/90
 */

#include <sys/param.h>
#include <sys/systm.h>

#include <machine/db_machdep.h>

#include <ddb/db_break.h>
#include <ddb/db_watch.h>
#include <ddb/db_lex.h>
#include <ddb/db_run.h>
#include <ddb/db_sym.h>
#include <ddb/db_output.h>
#include <ddb/db_command.h>
#include <ddb/db_extern.h>

/*
 * Watchpoints.
 */

boolean_t	db_watchpoints_inserted = TRUE;

#define	NWATCHPOINTS	100
struct db_watchpoint	db_watch_table[NWATCHPOINTS];
db_watchpoint_t		db_next_free_watchpoint = &db_watch_table[0];
db_watchpoint_t		db_free_watchpoints = 0;
db_watchpoint_t		db_watchpoint_list = 0;

db_watchpoint_t
db_watchpoint_alloc(void)
{
	db_watchpoint_t	watch;

	if ((watch = db_free_watchpoints) != 0) {
	    db_free_watchpoints = watch->link;
	    return (watch);
	}
	if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
	    db_printf("All watchpoints used.\n");
	    return (0);
	}
	watch = db_next_free_watchpoint;
	db_next_free_watchpoint++;

	return (watch);
}

void
db_watchpoint_free(db_watchpoint_t watch)
{
	watch->link = db_free_watchpoints;
	db_free_watchpoints = watch;
}

void
db_set_watchpoint(db_addr_t addr, vsize_t size)
{
	db_watchpoint_t	watch;

	/*
	 *	Should we do anything fancy with overlapping regions?
	 */

	for (watch = db_watchpoint_list; watch != 0; watch = watch->link)
		if (watch->loaddr == addr && watch->hiaddr == addr + size) {
			db_printf("Already set.\n");
			return;
		}

	watch = db_watchpoint_alloc();
	if (watch == 0) {
		db_printf("Too many watchpoints.\n");
		return;
	}

	watch->loaddr = addr;
	watch->hiaddr = addr+size;

	watch->link = db_watchpoint_list;
	db_watchpoint_list = watch;

	db_watchpoints_inserted = FALSE;
}

void
db_delete_watchpoint(db_addr_t addr)
{
	db_watchpoint_t	watch;
	db_watchpoint_t	*prev;

	for (prev = &db_watchpoint_list; (watch = *prev) != 0;
	   prev = &watch->link)
		if (watch->loaddr <= addr && addr < watch->hiaddr) {
			*prev = watch->link;
			db_watchpoint_free(watch);
			return;
		}

	db_printf("Not set.\n");
}

void
db_list_watchpoints(void)
{
	db_watchpoint_t	watch;

	if (db_watchpoint_list == 0) {
	    db_printf("No watchpoints set\n");
	    return;
	}

	db_printf("  Address  Size\n");
	for (watch = db_watchpoint_list; watch != 0; watch = watch->link)
		db_printf("%8lx  %lx\n",
		    watch->loaddr, watch->hiaddr - watch->loaddr);
}

/* Delete watchpoint */
/*ARGSUSED*/
void
db_deletewatch_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
	db_delete_watchpoint(addr);
}

/* Set watchpoint */
/*ARGSUSED*/
void
db_watchpoint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
	vsize_t 	size;
	db_expr_t	value;

	if (db_expression(&value))
	    size = (vsize_t) value;
	else
	    size = 4;
	db_skip_to_eol();

	db_set_watchpoint(addr, size);
}

/* list watchpoints */
/*ARGSUSED*/
void
db_listwatch_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
	db_list_watchpoints();
}

void
db_set_watchpoints(void)
{
	db_watchpoint_t	watch;

	if (!db_watchpoints_inserted && db_watchpoint_list != NULL) {
		for (watch = db_watchpoint_list; watch != 0;
		    watch = watch->link)
			pmap_protect(pmap_kernel(), trunc_page(watch->loaddr),
			    round_page(watch->hiaddr), PROT_READ);
		pmap_update(pmap_kernel());
		db_watchpoints_inserted = TRUE;
	}
}

void
db_clear_watchpoints(void)
{
	db_watchpoints_inserted = FALSE;
}


code:
/*	$OpenBSD: db_watch.h,v 1.9 2010/11/27 19:59:11 miod Exp $	*/
/*	$NetBSD: db_watch.h,v 1.9 1996/02/05 01:57:24 christos Exp $	*/

/*
 * Mach Operating System
 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 *
 * 	Author: David B. Golub, Carnegie Mellon University
 *	Date:	10/90
 */

#ifndef	_DDB_DB_WATCH_
#define	_DDB_DB_WATCH_

/*
 * Watchpoint.
 */
typedef struct db_watchpoint {
	db_addr_t loaddr;		/* from this address */
	db_addr_t hiaddr;		/* to this address */
	struct db_watchpoint *link;	/* link in in-use or free chain */
} *db_watchpoint_t;

db_watchpoint_t db_watchpoint_alloc(void);
void db_watchpoint_free(db_watchpoint_t);
void db_set_watchpoint(db_addr_t, vsize_t);
void db_delete_watchpoint(db_addr_t);
void db_list_watchpoints(void);
void db_deletewatch_cmd(db_expr_t, int, db_expr_t, char *);
void db_watchpoint_cmd(db_expr_t, int, db_expr_t, char *);
void db_listwatch_cmd(db_expr_t, int, db_expr_t, char *);
void db_set_watchpoints(void);
void db_clear_watchpoints(void);

#endif	/* _DDB_DB_WATCH_ */


code:
/*	$OpenBSD: db_write_cmd.c,v 1.14 2015/03/14 03:38:46 jsg Exp $	*/
/*	$NetBSD: db_write_cmd.c,v 1.6 1996/02/05 01:57:25 christos Exp $	*/

/*
 * Mach Operating System
 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 *
 *	Author: David B. Golub,  Carnegie Mellon University
 *	Date:	7/90
 */

#include <sys/param.h>
#include <sys/systm.h>

#include <machine/db_machdep.h>

#include <ddb/db_access.h>
#include <ddb/db_command.h>
#include <ddb/db_sym.h>
#include <ddb/db_extern.h>
#include <ddb/db_output.h>

/*
 * Write to file.
 */
/*ARGSUSED*/
void
db_write_cmd(db_expr_t	address, boolean_t have_addr, db_expr_t count,
    char *modif)
{
	db_addr_t	addr;
	db_expr_t	old_value;
	db_expr_t	new_value;
	int		size;
	boolean_t	wrote_one = FALSE;
	char		tmpfmt[28];

	addr = (db_addr_t) address;

	switch (modif[0]) {
	case 'b':
		size = 1;
		break;
	case 'h':
		size = 2;
		break;
	case 'l':
	case '\0':
		size = 4;
		break;
#ifdef __LP64__
	case 'q':
		size = 8;
		break;
#endif
	default:
		size = -1;
		db_error("Unknown size\n");
		/*NOTREACHED*/
	}

	while (db_expression(&new_value)) {
		old_value = db_get_value(addr, size, FALSE);
		db_printsym(addr, DB_STGY_ANY, db_printf);
		db_printf("\t\t%s\t", db_format(tmpfmt, sizeof tmpfmt,
		    old_value, DB_FORMAT_N, 0, 8));
		db_printf("=\t%s\n",  db_format(tmpfmt, sizeof tmpfmt,
		    new_value, DB_FORMAT_N, 0, 8));
		db_put_value(addr, size, new_value);
		addr += size;

		wrote_one = TRUE;
	}

	if (!wrote_one) {
		db_error("Nothing written.\n");
		/*NOTREACHED*/
	}

	db_next = addr;
	db_prev = addr - size;

	db_skip_to_eol();
}


code:
#!/usr/bin/perl
#	$OpenBSD: parse_structinfo.pl,v 1.3 2015/04/29 06:06:38 guenther Exp $
#
# Copyright (c) 2009 Miodrag Vallat.
# Copyright (c) 2013 Philip Guenther.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

# This ugly script parses the output of objdump -g in order to extract
# structure layout information, to be used by ddb.
#
# The output of this script is the following static data:
# - for each struct:
#   - its name
#   - its size (individual element size if an array)
#   - the number of elements in the array (1 if not)
#   - its first and last field indexes
# - for each field:
#   - its name
#   - its offset and size
#   - the index of the struct it is member of
# This allows fast struct -> field information retrieval.
#
# To retrieve information from a field size or offset, we also output
# the following reverse arrays:
# - for each offset, in ascending order, a variable length list of field
#   indexes.
# - for each size, in ascending order, a variable length list of field
#   indexes.
#
# The compromise here is that I want to minimize linear searches. Memory
# use is considered secondary, hence the back `pointer' to the struct in the
# fields array.

use strict;
use warnings;
use integer;
use IO::File;

use constant MAX_COLUMN => 72;

my $depth = 0;
my $ignore = 0;

my $cur_struct;

my $max_offs = 0;
my $max_fsize = 0;
my $max_ssize = 0;

# Variables used in generating the raw, textual output
my $txt;		# IO::File to write to
my @id2struct;		# mapping of objdump's struct ids to @structs idxes
my @subfield;		# list of subfields to dump at the end

# count of how many times each literal string appears
my %strings;
my @strings_by_len;
sub add_string
{
    my $string = shift;
    if ($strings{$string}++ == 0) {
	push @{ $strings_by_len[ length $string ] }, $string;
    }
}

my @structs;

my %offs_to_fields;
my %size_to_fields;
my @fields = ( {
	name	=> "",
	offs	=> 0,
	size	=> 0,
	items	=> 0,
	struct	=> 0,
    } );
sub new_field
{
    my($name, $offs, $size, $items, $id) = @_;

    $items //= 1;
    add_string($name);
    push @fields, {
	    name	=> $name,
	    offs	=> $offs,
	    size	=> $size,
	    items	=> $items,
	    struct	=> scalar(@structs),
	};
    $max_offs = $offs	if $offs > $max_offs;
    $max_fsize = $size	if $size > $max_fsize;
    push @{ $offs_to_fields{$offs} }, $#fields;
    push @{ $size_to_fields{$size} }, $#fields;
    if ($txt) {
	raw($offs, $size * $items, $cur_struct->{name}, $name);
	if (defined $id) {
	    push @subfield, [ $cur_struct->{name}, $name, $offs, $id ];
	}
    }
}

# Generate textual output for those who are ddb challenged.
$txt = IO::File->new("db_structinfo.txt", "w")
			or warn "$0: unable to create db_structinfo.txt: $!";
sub raw {
    my($offs, $size, $struct, $member) = @_;
    $txt->print(join("\t", $offs, $size, $offs+$size, $struct, $member), "\n");
}
$txt and $txt->print(join("\t", qw(offset size next struct member)), "\n");

while (<>) {
    chomp;	# strip record separator
    if (m!^struct (\w+) \{ /\* size (\d+) id (\d+) !) {
	$depth = 1;
	$cur_struct = {
		name	 => $1,
		size	 => $2,
		fieldmin => scalar(@fields)
	    };
	$id2struct[$3] = scalar(@structs);
	next
    }

    if (/^};/) {
	if ($depth == 0) {
	    $ignore--;
	    next
	}
	$depth = 0;
	if (scalar(@fields) == $cur_struct->{fieldmin}) {
	    # empty struct, ignore it
	    undef $cur_struct;
	    next
	}
	$cur_struct->{fieldmax} = $#fields;
	add_string( $cur_struct->{name} );
	$max_ssize = $cur_struct->{size} if $cur_struct->{size} > $max_ssize;
	push @structs, $cur_struct;
	next
    }

    next if /\{.*\}/;		# single line enum

    if (/\{/) {
	# subcomponent
	if ($depth) {
	    $depth++;
	} else {
	    $ignore++;
	}
	next
    }

    if (/\}/) {
	if ($ignore) {
	    $ignore--;
	    next
	}
	$depth--;
	next if $depth != 1;
	# FALL THROUGH
    }

    if (/bitsize (\d+), bitpos (\d+)/) {
	next if $ignore;
	next if $depth != 1;

	# Bitfields are a PITA... From a ddb point of view, we can't really
	# access storage units smaller than a byte.
	# So we'll report all bitfields as having size 0, and the
	# rounded down byte position where they start.
	my $cursize = ($1 % 8) ? 0 : ($1 / 8);
	my $curoffs = $2 / 8;

	# Try and gather the field name.
	# The most common case: not a function pointer or array
	if (m!\s(\**)(\w+);\s/\* bitsize!) {
	    my $pointer = $1 ne "";
	    my $name = $2;
	    # check for a struct id to match up
	    my($id) = !$pointer && m!/\* id (\d+) \*/.*;!;
	    new_field($name, $curoffs, $cursize, 1, $id);
	    next
	}

	# How about a function pointer?
	if (m!\s\**\(\*+(\w+)\) \(/\* unknown \*/\);\s/\* bitsize!) {
	    new_field($1, $curoffs, $cursize);
	    next
	}

	# Maybe it's an array
	if (m!\s(\**)([][:\w]+);\s/\* bitsize!) {
	    my $pointer = $1 ne "";
	    my $name = $2;
	    my $items = 1;
	    while ($name =~ s/\[(\d+)\]:\w+//) {
		$items *= $1;
	    }
	    # check for a struct id to match up
	    my($id) = !$pointer && m!/\* id (\d+) \*/.*;!;
	    new_field($name, $curoffs, $cursize / $items, $items, $id);
	    next
	}

	# skip any anonymous unions {
	next if m!\}; /\*!;

	# Should be nothing left
	print STDERR "unknown member type: $_\n";
	next
    }
}

# Do all the subfield processing
# XXX Should recurse into subsub...fields?
foreach my $sf (@subfield) {
    my($struct_name, $name, $offs, $id) = @$sf;
    my $s = $id2struct[$id];

    # We don't remember unions.  No point in doing so
    next if !defined $s;

    my $struct = $structs[$s];
    foreach my $i ($struct->{fieldmin} .. $struct->{fieldmax}) {
	my $f = $fields[$i];
	raw($offs + $f->{offs}, $f->{size} * $f->{items},
			$struct_name, "$name.$f->{name}");
    }
}

# Pick a type for ddb_field_off: if the offsets and sizes are all less than
# 65536 then we'll use u_short, otherwise u_int.
my $f_type = "u_short";
if ($max_offs > 65535 || $max_fsize > 65535 || $max_ssize > 65535) {
    $f_type = "u_int";
    print STDERR "Using u_int for struct/field sizes and offsets\n";
}

print <<EOM;
/*
 * THIS IS A GENERATED FILE.  DO NOT EDIT!
 */

#include <sys/param.h>
#include <sys/types.h>

typedef $f_type ddb_field_off;

struct ddb_struct_info {
	u_short name;
	ddb_field_off size;
	u_short fmin, fmax;
};
struct ddb_field_info {
	u_short name;
	u_short sidx;
	ddb_field_off offs;
	ddb_field_off size;
	u_short nitems;
};
struct ddb_field_offsets {
	ddb_field_off offs;
	u_short list;
};
struct ddb_field_sizes {
	ddb_field_off size;
	u_short list;
};
EOM

my $prefix = qq(static const char ddb_structfield_strings[] =\n\t"\\0);
my %string_to_offset = ( "" => 0 );
my $soff = 1;
for (my $len = $#strings_by_len; $len > 0; $len--) {
    foreach my $string (@{ $strings_by_len[$len] }) {
	next if exists $string_to_offset{$string};
	my $off = $string_to_offset{$string} = $soff;
	$soff += $len + 1;	# for the NUL
	print $prefix, $string;
	$prefix = qq(\\0"\n\t");

	# check for suffixes that are also strings
	for (my $o = 1; $o < $len; $o++) {
	    my $sstr = substr($string, $o);
	    next unless exists $strings{$sstr};
	    next if exists $string_to_offset{$sstr};
	    $string_to_offset{$sstr} = $off + $o;
	    #print STDERR "found $sstr inside $string\n";
	}
    }
}
print qq(";\n);

sub resolve_string
{
    my $string = shift;
    if (! exists $string_to_offset{$string}) {
	die "no mapping for $string";
    }
    return $string_to_offset{$string};
}

# Check for overflow and, if so, print some stats
if ($soff > 65535 || @structs > 65535 || @fields > 65535) {
    print STDERR <<EOM;
ERROR: value out of range of u_short  Time to change types?

max string offset: $soff
max field offset: $max_offs
max field size: $max_fsize
max struct size: $max_ssize
number of structs: ${\scalar(@structs)}
number of fields: ${\scalar(@fields)}
EOM
    exit 1
}

print "#define NSTRUCT ", scalar(@structs), "\n";
print "static const struct ddb_struct_info ddb_struct_info[NSTRUCT] = {\n";

foreach my $s (@structs) {
    my $name = resolve_string($s->{name});
    print "\t{ ",
	join(", ", $name, @{$s}{qw( size fieldmin fieldmax )}),
        " },\n";
}
printf "};\n\n";

print "#define NFIELD ", scalar(@fields), "\n";
print "static const struct ddb_field_info ddb_field_info[NFIELD] = {\n";
foreach my $f (@fields) {
    my $name = resolve_string($f->{name});
    print "\t{ ",
	join(", ", $name, @{$f}{qw( struct offs size items )}),
        " },\n";
}
printf "};\n\n";

# Given a mapping from values to fields that have that value, generate
# two C arrays: one containing lists of fields with each value, in order;
# the other indexing into that one for each value.  I.e., to get the
# fields that have a given value, find the value in the second array and
# then iterate from where that points into the first array until you hit
# an entry with field==0.
sub print_reverse_mapping
{
    my($prefix, $map, $max) = @_;
    print "static const ddb_field_off ddb_fields_by_${prefix}[] = {";
    my @heads;
    my $w = 0;
    foreach my $val (sort { $a <=> $b } keys %$map) {
	push @heads, [$val, $w];
	foreach my $field (@{ $map->{$val} }, 0) {
	    print( ($w++ % 10) == 0 ? "\n\t" : " ", $field, ",");
	}
    }
    print "\n};\n\n";
    print "#define $max ", scalar(@heads), "\n";
    print "static const struct ddb_field_${prefix}s",
		" ddb_field_${prefix}s[$max] = {\n";
    foreach my $h (@heads) {
	print "\t{ $h->[0], $h->[1] },\n";
    }
    print "};\n";
}

# reverse arrays
print_reverse_mapping("offset", \%offs_to_fields, "NOFFS");
print "\n";

# The size->field mapping isn't used by ddb currently, so don't output it
# print_reverse_mapping("size", \%size_to_fields, "NSIZES");


code: src/sys/dev

path: sys/dev/CVS/Repository


code: src/sys/dev/acpi

path: sys/dev/acpi/CVS/Repository