Index: head/sys/alpha/alpha/db_disasm.c =================================================================== --- head/sys/alpha/alpha/db_disasm.c (revision 131951) +++ head/sys/alpha/alpha/db_disasm.c (revision 131952) @@ -1,1093 +1,1089 @@ /* * Mach Operating System * Copyright (c) 1991,1990,1989,1988,1987 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. */ /* * File: db_disasm.c * Author: Alessandro Forin, Carnegie Mellon University * Date: 11/91 * * Disassembler for Alpha * * Modified for NetBSD/alpha by: * * Christopher G. Demetriou, Carnegie Mellon University * * Jason R. Thorpe, Numerical Aerospace Simulation Facility, * NASA Ames Research Center * * This code was derived exclusively from information available in * "Alpha Architecture Reference Manual", Richard L. Sites ed. * Digital Press, Burlington, MA 01803 * ISBN 1-55558-098-X, Order no. EY-L520E-DP */ #include /* RCS ID & Copyright macro defns */ /* __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.4 1997/09/16 22:52:40 thorpej Exp $"); */ __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include /* * This would belong in a header file, except noone else needs it */ typedef union { /* * All instructions are 32 bits wide, PAL included */ unsigned int bits; /* * Internal processor register access instrs * specify the IPR index, doubly specify the * (same) GP register as src/dest, and qualifiers * for the IPR set involved (abox/ibox/tmp) */ struct { unsigned index : 5, regset : 3, /* a,i,p */ xxx : 8, rs : 5, rd : 5, opcode : 6; } mXpr_format; /* * Load/store instructions have a 12 bit displacement, * and two register specifiers just as normal ld/st. * Four bits have special meanings: * phy: bypass the MMU (physical access) * alt: use mode in ALT register for checks, * or if PHY is also on locked/linked access * rwc: read-with-write-check (probew) * qw: quadword access */ struct { signed int displacement : 12; unsigned qw : 1, qualif : 3, rs : 5, rd : 5, opcode : 6; } mem_format; /* * Return from exception or interrupt has * a branch-like encoding, but only one * instantiation is actually usable. */ struct { unsigned xxx : 14, zero : 1, /* branch prediction! */ one : 1, rb : 5, /* r31 or stall */ ra : 5, /* r31 or stall */ opcode : 6; } rei_format; } pal_instruction; /* * Major opcodes */ static char *op_name[64] = { /* 0 */ "call_pal", "op1", "op2", "op3", "op4", "op5", "op6", "op7", /* 8 */ "lda", "ldah", "ldbu", "ldq_u","ldwu", "stw", "stb", "stq_u", /*16 */ "arit", "logical","bit","mul", "op20", "vaxf", "ieeef","anyf", /*24 */ "spec", "hw_mfpr","jump","hw_ld","intmisc","hw_mtpr","hw_rei","hw_st", /*32 */ "ldf", "ldg", "lds", "ldt", "stf", "stg", "sts", "stt", /*40 */ "ldl", "ldq", "ldl_l","ldq_l","stl", "stq", "stl_c","stq_c", /*48 */ "br", "fbeq", "fblt", "fble", "bsr", "fbne", "fbge", "fbgt", /*56 */ "blbc", "beq", "blt", "ble", "blbs", "bne", "bge", "bgt" }; /* * The function field is too big (7 or 11 bits), so the sub-tables * are addressed in a somewhat complicated manner to save * space. After all, alu operations is what RISCs are good at. */ struct tbl { const char *name; int code; }; static const struct tbl pal_op_tbl[] = { /* Common PAL function codes. */ { "halt", PAL_halt }, { "cflush", PAL_cflush }, { "draina", PAL_draina }, { "cserve", PAL_cserve, }, { "swppal", PAL_swppal }, { "ipir", PAL_ipir }, { "bpt", PAL_bpt }, { "bugchk", PAL_bugchk }, { "imb", PAL_imb }, { "rdunique", PAL_rdunique }, { "wrunique", PAL_wrunique }, { "gentrap", PAL_gentrap }, /* OSF/1 PAL function codes. */ { "osf1_rdmces", PAL_OSF1_rdmces }, { "osf1_wrmces", PAL_OSF1_wrmces }, { "osf1_wrfen", PAL_OSF1_wrfen }, { "osf1_wrvptptr", PAL_OSF1_wrvptptr }, { "osf1_swpctx", PAL_OSF1_swpctx }, { "osf1_wrval", PAL_OSF1_wrval }, { "osf1_rdval", PAL_OSF1_rdval }, { "osf1_tbi", PAL_OSF1_tbi }, { "osf1_wrent", PAL_OSF1_wrent }, { "osf1_swpipl", PAL_OSF1_swpipl }, { "osf1_rdps", PAL_OSF1_rdps }, { "osf1_wrkgp", PAL_OSF1_wrkgp }, { "osf1_wrusp", PAL_OSF1_wrusp }, { "osf1_wrperfmon", PAL_OSF1_wrperfmon }, { "osf1_rdusp", PAL_OSF1_rdusp }, { "osf1_whami", PAL_OSF1_whami }, { "osf1_retsys", PAL_OSF1_retsys }, { "osf1_rti", PAL_OSF1_rti }, { "osf1_callsys", PAL_OSF1_callsys }, { NULL, -1 }, }; static const char *pal_opname(int); static const char * pal_opname(op) int op; { static char unk[8]; int i; for (i = 0; pal_op_tbl[i].name != NULL; i++) { if (pal_op_tbl[i].code == op) return (pal_op_tbl[i].name); } snprintf(unk, sizeof(unk), "0x%x", op); return (unk); } /* HW (PAL) instruction qualifiers, stright tables */ static const char *mXpr_name[8] = { "", "/i", "/a", "/ai", "/p", "/pi", "/pa", "/pai" }; static const char *hwlds_name[8] = { "", "/r", "/a", "/ar", "/p", "/p?r", "_l-c", "_l-c/?r" }; /* * For this one we take the low nibble (valid values 0/2/9/b/d) * and shift it down one to get the row index. Within a row * we can just take the high nibble deprived of the high bit * (valid values 0/1/2/3/4/6). We could have used a flat 64 * entry array, but in this way we use just 48 pointers. * BUGFIX: the 'cmpbge 0x0f' opcode fits in here too */ static const char *arit_c0[8] = { "addl", 0, "addq", 0, "addl/v", 0, "addq/v", }; static const char *arit_c2[8] = { "s4addl", "s8addl", "s4addq", "s8addq", }; static const char *arit_c9[8] = { "subl", 0, "subq", 0, "subl/v", 0, "subq/v", }; static const char *arit_cB[8] = { "s4subl", "s8subl", "s4subq", "s8subq", }; static const char *arit_cD[8] = { 0, "cmpult", "cmpeq", "cmpule", "cmplt", 0, "cmple", }; static const char *arit_cF[1] = { "cmpbge" }; static const char **arit_opname[8] = { arit_c0, arit_c2, 0, 0, arit_c9, arit_cB, arit_cD, arit_cF }; static __inline const char *arit_name(int); static __inline const char * arit_name(op) int op; { static char unk[32]; const char *name = NULL; if (arit_opname[((op)&0xe)>>1]) name = arit_opname[((op)&0xe)>>1][((op)&0x70)>>4]; if (name != NULL) return (name); snprintf(unk, sizeof(unk), "?arit 0x%x?", op); return (unk); } /* * Something similar for this one, except there are only * 16 entries so the row indexing is done by enumeration * of the low nibble (valid values 0/4/6/8). Then we can * just shift the high nibble to index inside the row * (valid values are 0/2/4 or 1/2/4/6) * * There are two functions that don't play by these simple rules, * so we special-case them. */ static const char *logical_c0[4] = { "and", "or", "xor", 0 }; static const char *logical_c4[4] = { "cmovlbs", "cmoveq", "cmovlt", "cmovle" }; static const char *logical_c6[4] = { "cmovlbc", "cmovne", "cmovge", "cmovgt" }; static const char *logical_c8[4] = { "andnot", "ornot", "xornot", 0 }; static __inline const char *logical_name(int); static __inline const char * logical_name(op) int op; { static char unk[32]; const char *name = NULL; if (op == op_amask) return ("amask"); else if (op == op_implver) return ("implver"); switch (op & 0xf) { case 0: name = logical_c0[((op)>>5)&3]; break; case 4: name = logical_c4[((op)>>5)&3]; break; case 6: name = logical_c6[((op)>>5)&3]; break; case 8: name = logical_c8[((op)>>5)&3]; break; } if (name != NULL) return (name); snprintf(unk, sizeof(unk), "?logical 0x%x?", op); return (unk); } /* * This is the messy one. First, we single out the dense * case of a 3 in the high nibble (valid values 0/1/2/4/6/9/b/c). * Then the case of a 2 in the low nibble (valid values 0/1/2/5/6/7). * For the remaining codes (6/7/a/b) we do as above: high * nibble has valid values 0/1/2 or 5/6/7. The low nibble * can be used as row index picking bits 0 and 2, for the * high one just the lower two bits. */ static const char *bitop_c3[8] = { "zapnot", "mskql", "srl", "extql", "sll", "insql", "sra", 0 }; static const char *bitop_c2[8] = { "mskbl", "mskwl", "mskll", 0/*mskql*/, 0, "mskwh", "msklh", "mskqh" }; static const char *bitop_c67ab[4][4] = { /* a */ { 0, "extwh", "extlh", "extqh"}, /* b */ { "insbl", "inswl", "insll", 0 }, /* 6 */ { "extbl", "extwl", "extll", 0 }, /* 7 */ { 0, "inswh", "inslh", "insqh" }, }; static __inline const char *bitop_name(int); static __inline const char * bitop_name(op) int op; { static char unk[32]; const char *name = NULL; if ((op & 0x70) == 0x30) name = (op == op_zap) ? "zap" : bitop_c3[((op)&0xe)>>1]; else if ((op & 0xf) == 0x02) name = bitop_c2[(op)>>4]; else name = bitop_c67ab[(((op)&1)|(((op)&0x4)>>1))][(((op)&0x30)>>4)]; if (name != NULL) return (name); snprintf(unk, sizeof(unk), "?bit 0x%x?", op); return (unk); } /* * Only 5 entries in this one */ static const char *mul_opname[4] = { "mull", "mulq", "mull/v", "mulq/v" }; static __inline const char *mul_name(int); static __inline const char * mul_name(op) int op; { static char unk[32]; const char *name = NULL; name = (op == op_umulh) ? "umulh" : mul_opname[((op)>>5)&3]; if (name != NULL) return (name); snprintf(unk, sizeof(unk), "?mul 0x%x?", op); return (unk); } /* * These are few, the high nibble is enough to dispatch. * We single out the "f" case to halve the table size. */ static const char *special_opname[8] = { "drain_t", 0, "mb", 0, "fetch", "fetch_m", "rpcc", "rc" }; static __inline const char *special_name(int); static __inline const char * special_name(op) int op; { static char unk[32]; const char *name; name = (op == op_rs) ? "rs" : special_opname[(op)>>13]; if (name != NULL) return (name); snprintf(unk, sizeof(unk), "?special 0x%x?", op); return (unk); } /* * This is trivial */ static const char *jump_opname[4] = { "jmp", "jsr", "ret", "jcr" }; #define jump_name(ix) jump_opname[ix] /* * For all but 4 of these, we can dispatch on the lower nibble of * the "function". */ static const char *intmisc_opname_3x[16] = { "ctpop", "perr", "ctlz", "cttz", "unpkbw", "unpkbl", "pkwb", "pklb", "minsb8", "minsw4", "minub8", "minuw4", "maxub8", "maxuw4", "maxsb8", "maxsw4", }; static __inline const char *intmisc_name(int); static __inline const char * intmisc_name(op) int op; { static char unk[32]; if ((op & 0xf0) == 0x30) return (intmisc_opname_3x[op & 0x0f]); switch (op) { case op_sextb: return ("sextb"); case op_sextw: return ("sextw"); case op_ftoit: return ("ftoit"); case op_ftois: return ("ftois"); } snprintf(unk, sizeof(unk), "?intmisc 0x%x?", op); return (unk); } static const char *float_name(const struct tbl[], int, const char *type); static const char * float_name(tbl, op, type) const struct tbl tbl[]; int op; const char *type; { static char unk[32]; int i; for (i = 0; tbl[i].name != NULL; i++) { if (tbl[i].code == op) return (tbl[i].name); } snprintf(unk, sizeof(unk), "?%s 0x%x?", type, op); return (unk); } #define vaxf_name(op) float_name(vaxf_tbl, op, "vaxfl") #define ieeef_name(op) float_name(ieeef_tbl, op, "ieeefl") #define anyf_name(op) float_name(anyf_tbl, op, "anyfl") static const struct tbl anyf_tbl[] = { { "cvtlq", 0x010}, { "cpys", 0x020}, { "cpysn", 0x021}, { "cpyse", 0x022}, { "mt_fpcr", 0x024}, { "mf_fpcr", 0x025}, { "fcmoveq", 0x02a}, { "fcmovne", 0x02b}, { "fcmovlt", 0x02c}, { "fcmovge", 0x02d}, { "fcmovle", 0x02e}, { "fcmovgt", 0x02f}, { "cvtql", 0x030}, { "cvtql/v", 0x130}, { "cvtql/sv", 0x330}, { 0, 0}, }; static const struct tbl ieeef_tbl[] = { { "adds/c", 0x000}, { "subs/c", 0x001}, { "muls/c", 0x002}, { "divs/c", 0x003}, { "addt/c", 0x020}, { "subt/c", 0x021}, { "mult/c", 0x022}, { "divt/c", 0x023}, { "cvtts/c", 0x02c}, { "cvttq/c", 0x02f}, { "cvtqs/c", 0x03c}, { "cvtqt/c", 0x03e}, { "adds/m", 0x040}, { "subs/m", 0x041}, { "muls/m", 0x042}, { "divs/m", 0x043}, { "addt/m", 0x060}, { "subt/m", 0x061}, { "mult/m", 0x062}, { "divt/m", 0x063}, { "cvtts/m", 0x06c}, { "cvtqs/m", 0x07c}, { "cvtqt/m", 0x07e}, { "adds", 0x080}, { "subs", 0x081}, { "muls", 0x082}, { "divs", 0x083}, { "addt", 0x0a0}, { "subt", 0x0a1}, { "mult", 0x0a2}, { "divt", 0x0a3}, { "cmptun", 0x0a4}, { "cmpteq", 0x0a5}, { "cmptlt", 0x0a6}, { "cmptle", 0x0a7}, { "cvtts", 0x0ac}, { "cvttq", 0x0af}, { "cvtqs", 0x0bc}, { "cvtqt", 0x0be}, { "adds/d", 0x0c0}, { "subs/d", 0x0c1}, { "muls/d", 0x0c2}, { "divs/d", 0x0c3}, { "addt/d", 0x0e0}, { "subt/d", 0x0e1}, { "mult/d", 0x0e2}, { "divt/d", 0x0e3}, { "cvtts/d", 0x0ec}, { "cvtqs/d", 0x0fc}, { "cvtqt/d", 0x0fe}, { "adds/uc", 0x100}, { "subs/uc", 0x101}, { "muls/uc", 0x102}, { "divs/uc", 0x103}, { "addt/uc", 0x120}, { "subt/uc", 0x121}, { "mult/uc", 0x122}, { "divt/uc", 0x123}, { "cvtts/uc", 0x12c}, { "cvttq/vc", 0x12f}, { "adds/um", 0x140}, { "subs/um", 0x141}, { "muls/um", 0x142}, { "divs/um", 0x143}, { "addt/um", 0x160}, { "subt/um", 0x161}, { "mult/um", 0x162}, { "divt/um", 0x163}, { "cvtts/um", 0x16c}, { "adds/u", 0x180}, { "subs/u", 0x181}, { "muls/u", 0x182}, { "divs/u", 0x183}, { "addt/u", 0x1a0}, { "subt/u", 0x1a1}, { "mult/u", 0x1a2}, { "divt/u", 0x1a3}, { "cvtts/u", 0x1ac}, { "cvttq/v", 0x1af}, { "adds/ud", 0x1c0}, { "subs/ud", 0x1c1}, { "muls/ud", 0x1c2}, { "divs/ud", 0x1c3}, { "addt/ud", 0x1e0}, { "subt/ud", 0x1e1}, { "mult/ud", 0x1e2}, { "divt/ud", 0x1e3}, { "cvtts/ud", 0x1ec}, { "adds/suc", 0x500}, { "subs/suc", 0x501}, { "muls/suc", 0x502}, { "divs/suc", 0x503}, { "addt/suc", 0x520}, { "subt/suc", 0x521}, { "mult/suc", 0x522}, { "divt/suc", 0x523}, { "cvtts/suc", 0x52c}, { "cvttq/svc", 0x52f}, { "adds/sum", 0x540}, { "subs/sum", 0x541}, { "muls/sum", 0x542}, { "divs/sum", 0x543}, { "addt/sum", 0x560}, { "subt/sum", 0x561}, { "mult/sum", 0x562}, { "divt/sum", 0x563}, { "cvtts/sum", 0x56c}, { "adds/su", 0x580}, { "subs/su", 0x581}, { "muls/su", 0x582}, { "divs/su", 0x583}, { "addt/su", 0x5a0}, { "subt/su", 0x5a1}, { "mult/su", 0x5a2}, { "divt/su", 0x5a3}, { "cmptun/su", 0x5a4}, { "cmpteq/su", 0x5a5}, { "cmptlt/su", 0x5a6}, { "cmptle/su", 0x5a7}, { "cvtts/su", 0x5ac}, { "cvttq/sv", 0x5af}, { "adds/sud", 0x5c0}, { "subs/sud", 0x5c1}, { "muls/sud", 0x5c2}, { "divs/sud", 0x5c3}, { "addt/sud", 0x5e0}, { "subt/sud", 0x5e1}, { "mult/sud", 0x5e2}, { "divt/sud", 0x5e3}, { "cvtts/sud", 0x5ec}, { "adds/suic", 0x700}, { "subs/suic", 0x701}, { "muls/suic", 0x702}, { "divs/suic", 0x703}, { "addt/suic", 0x720}, { "subt/suic", 0x721}, { "mult/suic", 0x722}, { "divt/suic", 0x723}, { "cvtts/suic", 0x72c}, { "cvttq/svic", 0x72f}, { "cvtqs/suic", 0x73c}, { "cvtqt/suic", 0x73e}, { "adds/suim", 0x740}, { "subs/suim", 0x741}, { "muls/suim", 0x742}, { "divs/suim", 0x743}, { "addt/suim", 0x760}, { "subt/suim", 0x761}, { "mult/suim", 0x762}, { "divt/suim", 0x763}, { "cvtts/suim", 0x76c}, { "cvtqs/suim", 0x77c}, { "cvtqt/suim", 0x77e}, { "adds/sui", 0x780}, { "subs/sui", 0x781}, { "muls/sui", 0x782}, { "divs/sui", 0x783}, { "addt/sui", 0x7a0}, { "subt/sui", 0x7a1}, { "mult/sui", 0x7a2}, { "divt/sui", 0x7a3}, { "cvtts/sui", 0x7ac}, { "cvttq/svi", 0x7af}, { "cvtqs/sui", 0x7bc}, { "cvtqt/sui", 0x7be}, { "adds/suid", 0x7c0}, { "subs/suid", 0x7c1}, { "muls/suid", 0x7c2}, { "divs/suid", 0x7c3}, { "addt/suid", 0x7e0}, { "subt/suid", 0x7e1}, { "mult/suid", 0x7e2}, { "divt/suid", 0x7e3}, { "cvtts/suid", 0x7ec}, { "cvtqs/suid", 0x7fc}, { "cvtqt/suid", 0x7fe}, { 0, 0} }; static const struct tbl vaxf_tbl[] = { { "addf/c", 0x000}, { "subf/c", 0x001}, { "mulf/c", 0x002}, { "divf/c", 0x003}, { "cvtdg/c", 0x01e}, { "addg/c", 0x020}, { "subg/c", 0x021}, { "mulg/c", 0x022}, { "divg/c", 0x023}, { "cvtgf/c", 0x02c}, { "cvtgd/c", 0x02d}, { "cvtgq/c", 0x02f}, { "cvtqf/c", 0x03c}, { "cvtqg/c", 0x03e}, { "addf", 0x080}, { "subf", 0x081}, { "mulf", 0x082}, { "divf", 0x083}, { "cvtdg", 0x09e}, { "addg", 0x0a0}, { "subg", 0x0a1}, { "mulg", 0x0a2}, { "divg", 0x0a3}, { "cmpgeq", 0x0a5}, { "cmpglt", 0x0a6}, { "cmpgle", 0x0a7}, { "cvtgf", 0x0ac}, { "cvtgd", 0x0ad}, { "cvtgq", 0x0af}, { "cvtqf", 0x0bc}, { "cvtqg", 0x0be}, { "addf/uc", 0x100}, { "subf/uc", 0x101}, { "mulf/uc", 0x102}, { "divf/uc", 0x103}, { "cvtdg/uc", 0x11e}, { "addg/uc", 0x120}, { "subg/uc", 0x121}, { "mulg/uc", 0x122}, { "divg/uc", 0x123}, { "cvtgf/uc", 0x12c}, { "cvtgd/uc", 0x12d}, { "cvtgq/vc", 0x12f}, { "addf/u", 0x180}, { "subf/u", 0x181}, { "mulf/u", 0x182}, { "divf/u", 0x183}, { "cvtdg/u", 0x19e}, { "addg/u", 0x1a0}, { "subg/u", 0x1a1}, { "mulg/u", 0x1a2}, { "divg/u", 0x1a3}, { "cvtgf/u", 0x1ac}, { "cvtgd/u", 0x1ad}, { "cvtgq/v", 0x1af}, { "addf/sc", 0x400}, { "subf/sc", 0x401}, { "mulf/sc", 0x402}, { "divf/sc", 0x403}, { "cvtdg/sc", 0x41e}, { "addg/sc", 0x420}, { "subg/sc", 0x421}, { "mulg/sc", 0x422}, { "divg/sc", 0x423}, { "cvtgf/sc", 0x42c}, { "cvtgd/sc", 0x42d}, { "cvtgq/sc", 0x42f}, { "cvtqf/sc", 0x43c}, { "cvtqg/sc", 0x43e}, { "addf/s", 0x480}, { "subf/s", 0x481}, { "mulf/s", 0x482}, { "divf/s", 0x483}, { "cvtdg/s", 0x49e}, { "addg/s", 0x4a0}, { "subg/s", 0x4a1}, { "mulg/s", 0x4a2}, { "divg/s", 0x4a3}, { "cmpgeq/s", 0x4a5}, { "cmpglt/s", 0x4a6}, { "cmpgle/s", 0x4a7}, { "cvtgf/s", 0x4ac}, { "cvtgd/s", 0x4ad}, { "cvtgq/s", 0x4af}, { "cvtqf/s", 0x4bc}, { "cvtqg/s", 0x4be}, { "addf/suc", 0x500}, { "subf/suc", 0x501}, { "mulf/suc", 0x502}, { "divf/suc", 0x503}, { "cvtdg/suc", 0x51e}, { "addg/suc", 0x520}, { "subg/suc", 0x521}, { "mulg/suc", 0x522}, { "divg/suc", 0x523}, { "cvtgf/suc", 0x52c}, { "cvtgd/suc", 0x52d}, { "cvtgq/svc", 0x52f}, { "addf/su", 0x580}, { "subf/su", 0x581}, { "mulf/su", 0x582}, { "divf/su", 0x583}, { "cvtdg/su", 0x59e}, { "addg/su", 0x5a0}, { "subg/su", 0x5a1}, { "mulg/su", 0x5a2}, { "divg/su", 0x5a3}, { "cvtgf/su", 0x5ac}, { "cvtgd/su", 0x5ad}, { "cvtgq/sv", 0x5af}, { 0, 0} }; /* * General purpose registers */ static const char *name_of_register[32] = { "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9", "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero" }; static int regcount; /* how many regs used in this inst */ static int regnum[3]; /* which regs used in this inst */ static const char *register_name(int); static const char * register_name (ireg) int ireg; { int i; for (i = 0; i < regcount; i++) if (regnum[i] == ireg) break; if (i >= regcount) regnum[regcount++] = ireg; return (name_of_register[ireg]); } /* * Disassemble instruction at 'loc'. 'altfmt' specifies an * (optional) alternate format. Return address of start of * next instruction. */ -int alpha_print_instruction(db_addr_t, alpha_instruction, boolean_t); -db_addr_t -db_disasm(loc, altfmt) - db_addr_t loc; - boolean_t altfmt; +static int +alpha_print_instr(db_addr_t iadr, alpha_instruction i, boolean_t showregs) { - alpha_instruction inst; - - inst.bits = db_get_value(loc, 4, 0); - - loc += alpha_print_instruction(loc, inst, altfmt); - return (loc); -} - -int -alpha_print_instruction(iadr, i, showregs) - db_addr_t iadr; - alpha_instruction i; - boolean_t showregs; -{ const char *opcode; int ireg; long signed_immediate; boolean_t fstore; pal_instruction p; regcount = 0; fstore = FALSE; opcode = op_name[i.mem_format.opcode]; /* * Dispatch directly on the opcode, save code * duplication sometimes via "harmless gotos". */ switch (i.mem_format.opcode) { case op_pal: /* "call_pal" is a long string; just use a space. */ db_printf("%s %s", opcode, pal_opname(i.pal_format.function)); break; case op_lda: case op_ldah: case op_ldbu: case op_ldq_u: case op_ldwu: case op_stw: case op_stb: case op_stq_u: /* * These loadstores are here to make compiling the * switch a bit easier. Could embellish the output * someday, too. */ goto loadstore; break; case op_arit: /* * For this and the following three groups we * just need different opcode strings */ opcode = arit_name(i.operate_lit_format.function); goto operate; break; case op_logical: opcode = logical_name(i.operate_lit_format.function); goto operate; break; case op_bit: opcode = bitop_name(i.operate_lit_format.function); goto operate; break; case op_mul: opcode = mul_name(i.operate_lit_format.function); operate: /* * Nice and uniform, just check for literals */ db_printf("%s\t%s,", opcode, register_name(i.operate_lit_format.rs)); if (i.operate_lit_format.one) db_printf("#0x%x", i.operate_lit_format.literal); else db_printf("%s", register_name(i.operate_reg_format.rt)); db_printf(",%s", register_name(i.operate_lit_format.rd)); break; case op_vax_float: /* * The three floating point groups are even simpler */ opcode = vaxf_name(i.float_format.function); goto foperate; break; case op_ieee_float: opcode = ieeef_name(i.float_format.function); goto foperate; break; case op_any_float: opcode = anyf_name(i.float_format.function); foperate: db_printf("%s\tf%d,f%d,f%d", opcode, i.float_format.fs, i.float_format.ft, i.float_format.fd); break; case op_special: /* * Miscellaneous. */ { register unsigned int code; code = (i.mem_format.displacement)&0xffff; opcode = special_name(code); switch (code) { case op_fetch: case op_fetch_m: db_printf("%s\t0(%s)", opcode, register_name(i.mem_format.rs)); break; case op_rpcc: case op_rc: case op_rs: db_printf("%s\t%s", opcode, register_name(i.mem_format.rd)); break; case op_draint: case op_mb: default: db_printf("%s", opcode); break; } } break; case op_j: /* * Jump instructions really are of two sorts, * depending on the use of the hint info. */ opcode = jump_name(i.jump_format.action); switch (i.jump_format.action) { case op_jmp: case op_jsr: db_printf("%s\t%s,(%s),", opcode, register_name(i.jump_format.rd), register_name(i.jump_format.rs)); signed_immediate = i.jump_format.hint; goto branch_displacement; break; case op_ret: case op_jcr: db_printf("%s\t%s,(%s)", opcode, register_name(i.jump_format.rd), register_name(i.jump_format.rs)); break; } break; case op_intmisc: /* * These are just in "operate" format. */ opcode = intmisc_name(i.operate_lit_format.function); goto operate; break; /* HW instructions, possibly chip-specific XXXX */ case op_pal19: /* "hw_mfpr" */ case op_pal1d: /* "hw_mtpr" */ p.bits = i.bits; db_printf("\t%s%s\t%s, %d", opcode, mXpr_name[p.mXpr_format.regset], register_name(p.mXpr_format.rd), p.mXpr_format.index); break; case op_pal1b: /* "hw_ld" */ case op_pal1f: /* "hw_st" */ p.bits = i.bits; db_printf("\t%s%c%s\t%s,", opcode, (p.mem_format.qw) ? 'q' : 'l', hwlds_name[p.mem_format.qualif], register_name(p.mem_format.rd)); signed_immediate = (long)p.mem_format.displacement; goto loadstore_address; case op_pal1e: /* "hw_rei" */ db_printf("\t%s", opcode); break; case op_ldf: case op_ldg: case op_lds: case op_ldt: case op_stf: case op_stg: case op_sts: case op_stt: fstore = TRUE; /* FALLTHROUGH */ case op_ldl: case op_ldq: case op_ldl_l: case op_ldq_l: case op_stl: case op_stq: case op_stl_c: case op_stq_c: /* * Memory operations, including floats */ loadstore: if (fstore) db_printf("%s\tf%d,", opcode, i.mem_format.rd); else db_printf("%s\t%s,", opcode, register_name(i.mem_format.rd)); signed_immediate = (long)i.mem_format.displacement; loadstore_address: db_printf("%#lx(%s)", signed_immediate, register_name(i.mem_format.rs)); /* * For convenience, do the address computation */ if (showregs) { if (i.mem_format.opcode == op_ldah) signed_immediate <<= 16; db_printf(" <0x%lx>", signed_immediate + - db_register_value(DDB_REGS, i.mem_format.rs)); + db_register_value(i.mem_format.rs)); } break; case op_br: case op_fbeq: case op_fblt: case op_fble: case op_bsr: case op_fbne: case op_fbge: case op_fbgt: case op_blbc: case op_beq: case op_blt: case op_ble: case op_blbs: case op_bne: case op_bge: case op_bgt: /* * We want to know where we are branching to */ signed_immediate = (long)i.branch_format.displacement; db_printf("%s\t%s,", opcode, register_name(i.branch_format.rd)); branch_displacement: db_printsym(iadr + sizeof(alpha_instruction) + (signed_immediate << 2), DB_STGY_PROC); break; default: /* * Shouldn't happen */ db_printf("? 0x%x ?", i.bits); } /* * Print out the registers used in this instruction */ if (showregs && regcount > 0) { db_printf("\t<"); for (ireg = 0; ireg < regcount; ireg++) { if (ireg != 0) db_printf(","); db_printf("%s=0x%lx", name_of_register[regnum[ireg]], - db_register_value(DDB_REGS, regnum[ireg])); + db_register_value(regnum[ireg])); } db_printf(">"); } db_printf("\n"); return (sizeof(alpha_instruction)); +} + +db_addr_t +db_disasm(loc, altfmt) + db_addr_t loc; + boolean_t altfmt; +{ + alpha_instruction inst; + + inst.bits = db_get_value(loc, 4, 0); + + loc += alpha_print_instr(loc, inst, altfmt); + return (loc); } Index: head/sys/alpha/alpha/db_interface.c =================================================================== --- head/sys/alpha/alpha/db_interface.c (revision 131951) +++ head/sys/alpha/alpha/db_interface.c (revision 131952) @@ -1,577 +1,452 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. * * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) */ /* * Parts of this file are derived from Mach 3: * * File: alpha_instruction.c * Author: Alessandro Forin, Carnegie Mellon University * Date: 6/92 */ /* * Interface to DDB. * * Modified for NetBSD/alpha by: * * Christopher G. Demetriou, Carnegie Mellon University * * Jason R. Thorpe, Numerical Aerospace Simulation Facility, * NASA Ames Research Center */ #include /* RCS ID & Copyright macro defns */ /* __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.2 1997/09/16 19:07:19 thorpej Exp $"); */ __FBSDID("$FreeBSD$"); #include -#include -#include #include -#include #include -#include -#include +#include +#include #include +#include #include #include #include #include #include #include #include #include #include #include -#include -static jmp_buf *db_nofault = 0; -extern jmp_buf db_jmpbuf; +static db_varfcn_t db_frame; -extern void gdb_handle_exception(db_regs_t *, int, int); - -#if 0 -extern char *trap_type[]; -extern int trap_types; -#endif - -int db_active; - -void ddbprinttrap(unsigned long, unsigned long, unsigned long, - unsigned long); - struct db_variable db_regs[] = { - { "v0", &ddb_regs.tf_regs[FRAME_V0], FCN_NULL }, - { "t0", &ddb_regs.tf_regs[FRAME_T0], FCN_NULL }, - { "t1", &ddb_regs.tf_regs[FRAME_T1], FCN_NULL }, - { "t2", &ddb_regs.tf_regs[FRAME_T2], FCN_NULL }, - { "t3", &ddb_regs.tf_regs[FRAME_T3], FCN_NULL }, - { "t4", &ddb_regs.tf_regs[FRAME_T4], FCN_NULL }, - { "t5", &ddb_regs.tf_regs[FRAME_T5], FCN_NULL }, - { "t6", &ddb_regs.tf_regs[FRAME_T6], FCN_NULL }, - { "t7", &ddb_regs.tf_regs[FRAME_T7], FCN_NULL }, - { "s0", &ddb_regs.tf_regs[FRAME_S0], FCN_NULL }, - { "s1", &ddb_regs.tf_regs[FRAME_S1], FCN_NULL }, - { "s2", &ddb_regs.tf_regs[FRAME_S2], FCN_NULL }, - { "s3", &ddb_regs.tf_regs[FRAME_S3], FCN_NULL }, - { "s4", &ddb_regs.tf_regs[FRAME_S4], FCN_NULL }, - { "s5", &ddb_regs.tf_regs[FRAME_S5], FCN_NULL }, - { "s6", &ddb_regs.tf_regs[FRAME_S6], FCN_NULL }, - { "a0", &ddb_regs.tf_regs[FRAME_A0], FCN_NULL }, - { "a1", &ddb_regs.tf_regs[FRAME_A1], FCN_NULL }, - { "a2", &ddb_regs.tf_regs[FRAME_A2], FCN_NULL }, - { "a3", &ddb_regs.tf_regs[FRAME_A3], FCN_NULL }, - { "a4", &ddb_regs.tf_regs[FRAME_A4], FCN_NULL }, - { "a5", &ddb_regs.tf_regs[FRAME_A5], FCN_NULL }, - { "t8", &ddb_regs.tf_regs[FRAME_T8], FCN_NULL }, - { "t9", &ddb_regs.tf_regs[FRAME_T9], FCN_NULL }, - { "t10", &ddb_regs.tf_regs[FRAME_T10], FCN_NULL }, - { "t11", &ddb_regs.tf_regs[FRAME_T11], FCN_NULL }, - { "ra", &ddb_regs.tf_regs[FRAME_RA], FCN_NULL }, - { "t12", &ddb_regs.tf_regs[FRAME_T12], FCN_NULL }, - { "at", &ddb_regs.tf_regs[FRAME_AT], FCN_NULL }, - { "gp", &ddb_regs.tf_regs[FRAME_GP], FCN_NULL }, - { "sp", &ddb_regs.tf_regs[FRAME_SP], FCN_NULL }, - { "pc", &ddb_regs.tf_regs[FRAME_PC], FCN_NULL }, - { "ps", &ddb_regs.tf_regs[FRAME_PS], FCN_NULL }, - { "ai", &ddb_regs.tf_regs[FRAME_T11], FCN_NULL }, - { "pv", &ddb_regs.tf_regs[FRAME_T12], FCN_NULL }, + { "v0", (db_expr_t *)FRAME_V0, db_frame }, + { "t0", (db_expr_t *)FRAME_T0, db_frame }, + { "t1", (db_expr_t *)FRAME_T1, db_frame }, + { "t2", (db_expr_t *)FRAME_T2, db_frame }, + { "t3", (db_expr_t *)FRAME_T3, db_frame }, + { "t4", (db_expr_t *)FRAME_T4, db_frame }, + { "t5", (db_expr_t *)FRAME_T5, db_frame }, + { "t6", (db_expr_t *)FRAME_T6, db_frame }, + { "t7", (db_expr_t *)FRAME_T7, db_frame }, + { "s0", (db_expr_t *)FRAME_S0, db_frame }, + { "s1", (db_expr_t *)FRAME_S1, db_frame }, + { "s2", (db_expr_t *)FRAME_S2, db_frame }, + { "s3", (db_expr_t *)FRAME_S3, db_frame }, + { "s4", (db_expr_t *)FRAME_S4, db_frame }, + { "s5", (db_expr_t *)FRAME_S5, db_frame }, + { "s6", (db_expr_t *)FRAME_S6, db_frame }, + { "a0", (db_expr_t *)FRAME_A0, db_frame }, + { "a1", (db_expr_t *)FRAME_A1, db_frame }, + { "a2", (db_expr_t *)FRAME_A2, db_frame }, + { "a3", (db_expr_t *)FRAME_A3, db_frame }, + { "a4", (db_expr_t *)FRAME_A4, db_frame }, + { "a5", (db_expr_t *)FRAME_A5, db_frame }, + { "t8", (db_expr_t *)FRAME_T8, db_frame }, + { "t9", (db_expr_t *)FRAME_T9, db_frame }, + { "t10", (db_expr_t *)FRAME_T10, db_frame }, + { "t11", (db_expr_t *)FRAME_T11, db_frame }, + { "ra", (db_expr_t *)FRAME_RA, db_frame }, + { "t12", (db_expr_t *)FRAME_T12, db_frame }, + { "at", (db_expr_t *)FRAME_AT, db_frame }, + { "gp", (db_expr_t *)FRAME_GP, db_frame }, + { "sp", (db_expr_t *)FRAME_SP, db_frame }, + { "pc", (db_expr_t *)FRAME_PC, db_frame }, + { "ps", (db_expr_t *)FRAME_PS, db_frame }, + { "ai", (db_expr_t *)FRAME_T11, db_frame }, + { "pv", (db_expr_t *)FRAME_T12, db_frame }, }; struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); -/* - * Print trap reason. - */ -void -ddbprinttrap(a0, a1, a2, entry) - unsigned long a0, a1, a2, entry; +static int +db_frame(struct db_variable *vp, db_expr_t *valuep, int op) { - /* XXX Implement. */ - - printf("ddbprinttrap(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", a0, a1, a2, - entry); + if (kdb_frame == NULL) + return (0); + if (op == DB_VAR_GET) + *valuep = kdb_frame->tf_regs[(uintptr_t)vp->valuep]; + else + kdb_frame->tf_regs[(uintptr_t)vp->valuep] = *valuep; + return (1); } /* - * ddb_trap - field a kernel trap + * Read bytes from kernel address space for debugger. */ int -kdb_trap(a0, a1, a2, entry, regs) - unsigned long a0, a1, a2, entry; - db_regs_t *regs; +db_read_bytes(vm_offset_t addr, size_t size, char *data) { - int ddb_mode = !(boothowto & RB_GDB); - register_t s; + jmp_buf jb; + void *prev_jb; + char *src; + int ret; - /* - * Don't bother checking for usermode, since a benign entry - * by the kernel (call to Debugger() or a breakpoint) has - * already checked for usermode. If neither of those - * conditions exist, something Bad has happened. - */ - - if (entry != ALPHA_KENTRY_IF || - (a0 != ALPHA_IF_CODE_BUGCHK && a0 != ALPHA_IF_CODE_BPT - && a0 != ALPHA_IF_CODE_GENTRAP)) { -#if 0 - if (ddb_mode) { - db_printf("ddbprinttrap from 0x%lx\n", /* XXX */ - regs->tf_regs[FRAME_PC]); - ddbprinttrap(a0, a1, a2, entry); - /* - * Tell caller "We did NOT handle the trap." - * Caller should panic, or whatever. - */ - return (0); - } -#endif - if (db_nofault) { - jmp_buf *no_fault = db_nofault; - db_nofault = 0; - longjmp(*no_fault, 1); - } + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + src = (char *)addr; + while (size-- > 0) + *data++ = *src++; } - - /* - * XXX Should switch to DDB's own stack, here. - */ - - ddb_regs = *regs; - - s = intr_disable(); - -#ifdef SMP -#ifdef DIAGNOSTIC - db_printf("stopping %x\n", PCPU_GET(other_cpus)); -#endif - stop_cpus(PCPU_GET(other_cpus)); -#ifdef DIAGNOSTIC - db_printf("stopped_cpus=%x\n", stopped_cpus); -#endif -#endif - - db_active++; - - if (ddb_mode) { - cndbctl(TRUE); /* DDB active, unblank video */ - db_trap(entry, a0); /* Where the work happens */ - cndbctl(FALSE); /* DDB inactive */ - } else - gdb_handle_exception(&ddb_regs, entry, a0); - - db_active--; - -#ifdef SMP - restart_cpus(stopped_cpus); -#endif - - intr_restore(s); - - *regs = ddb_regs; - - /* - * Tell caller "We HAVE handled the trap." - */ - return (1); + (void)kdb_jmpbuf(prev_jb); + return (ret); } /* - * Read bytes from kernel address space for debugger. - */ -void -db_read_bytes(addr, size, data) - vm_offset_t addr; - register size_t size; - register char *data; -{ - register char *src; - - db_nofault = &db_jmpbuf; - - src = (char *)addr; - while (size-- > 0) - *data++ = *src++; - - db_nofault = 0; -} - -/* * Write bytes to kernel address space for debugger. */ -void -db_write_bytes(addr, size, data) - vm_offset_t addr; - register size_t size; - register char *data; +int +db_write_bytes(vm_offset_t addr, size_t size, char *data) { - register char *dst; + jmp_buf jb; + void *prev_jb; + char *dst; + int ret; - db_nofault = &db_jmpbuf; - - dst = (char *)addr; - while (size-- > 0) - *dst++ = *data++; - alpha_pal_imb(); - - db_nofault = 0; + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + dst = (char *)addr; + while (size-- > 0) + *dst++ = *data++; + alpha_pal_imb(); + } + (void)kdb_jmpbuf(prev_jb); + return (ret); } -void -Debugger(const char* msg) -{ - u_int saveintr; - - printf("%s\n", msg); - saveintr = alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH); - __asm("call_pal 0x81"); /* XXX bugchk */ - alpha_pal_swpipl(saveintr); -} - /* * Alpha-specific ddb commands: * * halt set halt bit in rpb and halt * reboot set reboot bit in rpb and halt */ DB_COMMAND(halt, db_mach_halt) { prom_halt(1); } DB_COMMAND(reboot, db_mach_reboot) { prom_halt(0); } /* * Map Alpha register numbers to trapframe/db_regs_t offsets. */ static int reg_to_frame[32] = { FRAME_V0, FRAME_T0, FRAME_T1, FRAME_T2, FRAME_T3, FRAME_T4, FRAME_T5, FRAME_T6, FRAME_T7, FRAME_S0, FRAME_S1, FRAME_S2, FRAME_S3, FRAME_S4, FRAME_S5, FRAME_S6, FRAME_A0, FRAME_A1, FRAME_A2, FRAME_A3, FRAME_A4, FRAME_A5, FRAME_T8, FRAME_T9, FRAME_T10, FRAME_T11, FRAME_RA, FRAME_T12, FRAME_AT, FRAME_GP, FRAME_SP, -1, /* zero */ }; u_long -db_register_value(regs, regno) - db_regs_t *regs; - int regno; +db_register_value(int regno) { if (regno > 31 || regno < 0) { db_printf(" **** STRANGE REGISTER NUMBER %d **** ", regno); return (0); } if (regno == 31) return (0); - return (regs->tf_regs[reg_to_frame[regno]]); + return (kdb_frame->tf_regs[reg_to_frame[regno]]); } /* * Support functions for software single-step. */ boolean_t db_inst_call(ins) int ins; { alpha_instruction insn; insn.bits = ins; return ((insn.branch_format.opcode == op_bsr) || ((insn.jump_format.opcode == op_j) && (insn.jump_format.action & 1))); } boolean_t db_inst_return(ins) int ins; { alpha_instruction insn; insn.bits = ins; return ((insn.jump_format.opcode == op_j) && (insn.jump_format.action == op_ret)); } boolean_t db_inst_trap_return(ins) int ins; { alpha_instruction insn; insn.bits = ins; return ((insn.pal_format.opcode == op_pal) && (insn.pal_format.function == PAL_OSF1_rti)); } boolean_t db_inst_branch(ins) int ins; { alpha_instruction insn; insn.bits = ins; switch (insn.branch_format.opcode) { case op_j: case op_br: case op_fbeq: case op_fblt: case op_fble: case op_fbne: case op_fbge: case op_fbgt: case op_blbc: case op_beq: case op_blt: case op_ble: case op_blbs: case op_bne: case op_bge: case op_bgt: return (TRUE); } return (FALSE); } boolean_t db_inst_unconditional_flow_transfer(ins) int ins; { alpha_instruction insn; insn.bits = ins; switch (insn.branch_format.opcode) { case op_j: case op_br: return (TRUE); case op_pal: switch (insn.pal_format.function) { case PAL_OSF1_retsys: case PAL_OSF1_rti: case PAL_OSF1_callsys: return (TRUE); } } return (FALSE); } -#if 0 boolean_t -db_inst_spill(ins, regn) - int ins, regn; -{ - alpha_instruction insn; - - insn.bits = ins; - return ((insn.mem_format.opcode == op_stq) && - (insn.mem_format.rd == regn)); -} -#endif - -boolean_t db_inst_load(ins) int ins; { alpha_instruction insn; insn.bits = ins; /* Loads. */ if (insn.mem_format.opcode == op_ldbu || insn.mem_format.opcode == op_ldq_u || insn.mem_format.opcode == op_ldwu) return (TRUE); if ((insn.mem_format.opcode >= op_ldf) && (insn.mem_format.opcode <= op_ldt)) return (TRUE); if ((insn.mem_format.opcode >= op_ldl) && (insn.mem_format.opcode <= op_ldq_l)) return (TRUE); /* Prefetches. */ if (insn.mem_format.opcode == op_special) { /* Note: MB is treated as a store. */ if ((insn.mem_format.displacement == (short)op_fetch) || (insn.mem_format.displacement == (short)op_fetch_m)) return (TRUE); } return (FALSE); } boolean_t db_inst_store(ins) int ins; { alpha_instruction insn; insn.bits = ins; /* Stores. */ if (insn.mem_format.opcode == op_stw || insn.mem_format.opcode == op_stb || insn.mem_format.opcode == op_stq_u) return (TRUE); if ((insn.mem_format.opcode >= op_stf) && (insn.mem_format.opcode <= op_stt)) return (TRUE); if ((insn.mem_format.opcode >= op_stl) && (insn.mem_format.opcode <= op_stq_c)) return (TRUE); /* Barriers. */ if (insn.mem_format.opcode == op_special) { if (insn.mem_format.displacement == op_mb) return (TRUE); } return (FALSE); } db_addr_t -db_branch_taken(ins, pc, regs) - int ins; - db_addr_t pc; - db_regs_t *regs; +db_branch_taken(int ins, db_addr_t pc) { alpha_instruction insn; db_addr_t newpc; insn.bits = ins; switch (insn.branch_format.opcode) { /* * Jump format: target PC is (contents of instruction's "RB") & ~3. */ case op_j: - newpc = db_register_value(regs, insn.jump_format.rs) & ~3; + newpc = db_register_value(insn.jump_format.rs) & ~3; break; /* * Branch format: target PC is * (new PC) + (4 * sign-ext(displacement)). */ case op_br: case op_fbeq: case op_fblt: case op_fble: case op_bsr: case op_fbne: case op_fbge: case op_fbgt: case op_blbc: case op_beq: case op_blt: case op_ble: case op_blbs: case op_bne: case op_bge: case op_bgt: newpc = (insn.branch_format.displacement << 2) + (pc + 4); break; default: printf("DDB: db_inst_branch_taken on non-branch!\n"); newpc = pc; /* XXX */ } return (newpc); } void db_show_mdpcpu(struct pcpu *pc) { db_printf("ipis = 0x%lx\n", pc->pc_pending_ipis); db_printf("next ASN = %d\n", pc->pc_next_asn); } Index: head/sys/alpha/alpha/db_trace.c =================================================================== --- head/sys/alpha/alpha/db_trace.c (revision 131951) +++ head/sys/alpha/alpha/db_trace.c (revision 131952) @@ -1,434 +1,386 @@ /* $NetBSD: db_trace.c,v 1.9 2000/12/13 03:16:36 mycroft Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, * NASA Ames Research Center. * * This code is derived from software contributed to The NetBSD Foundation * by Ross Harvey. * * 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``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 FOUNDATION OR CONTRIBUTORS * 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 /* RCS ID & Copyright macro defns */ /*__KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.9 2000/12/13 03:16:36 mycroft Exp $");*/ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include #include #include #include #include #include #include #include -struct trace_request { - register_t ksp; - register_t pc; -}; - /* * Information about the `standard' Alpha function prologue. */ struct prologue_info { int pi_reg_offset[32]; /* offset of registers in stack frame */ u_int32_t pi_regmask; /* which registers are in frame */ int pi_frame_size; /* frame size */ }; /* * We use several symbols to take special action: * * Trap vectors, which use a different (fixed-size) stack frame: * * XentArith * XentIF * XentInt * XentMM * XentSys * XentUna */ static struct special_symbol { uintptr_t ss_val; const char *ss_note; } special_symbols[] = { { (uintptr_t)&XentArith, "arithmetic trap" }, { (uintptr_t)&XentIF, "instruction fault" }, { (uintptr_t)&XentInt, "interrupt" }, { (uintptr_t)&XentMM, "memory management fault" }, { (uintptr_t)&XentSys, "syscall" }, { (uintptr_t)&XentUna, "unaligned access fault" }, { (uintptr_t)&XentRestart, "console restart" }, { 0, NULL } }; int db_md_set_watchpoint(db_expr_t addr, db_expr_t size); int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size); void db_md_list_watchpoints(void); /* * Decode the function prologue for the function we're in, and note * which registers are stored where, and how large the stack frame is. */ static int decode_prologue(db_addr_t callpc, db_addr_t func, struct prologue_info *pi) { long signed_immediate; alpha_instruction ins; db_expr_t pc; pi->pi_regmask = 0; pi->pi_frame_size = 0; #define CHECK_FRAMESIZE \ do { \ if (pi->pi_frame_size != 0) { \ db_printf("frame size botch: adjust register offsets?\n"); \ return (1); \ } \ } while (0) for (pc = func; pc < callpc; pc += sizeof(alpha_instruction)) { ins.bits = *(unsigned int *)pc; if (ins.memory_format.opcode == op_lda && ins.memory_format.ra == 30 && ins.memory_format.rb == 30) { /* * GCC 2.7-style stack adjust: * * lda sp, -64(sp) */ signed_immediate = (long)ins.mem_format.displacement; #if 1 if (signed_immediate > 0) { db_printf("prologue botch: displacement %ld\n", signed_immediate); return (1); } #endif CHECK_FRAMESIZE; pi->pi_frame_size += -signed_immediate; } else if (ins.operate_lit_format.opcode == op_arit && ins.operate_lit_format.function == op_subq && ins.operate_lit_format.rs == 30 && ins.operate_lit_format.rd == 30) { /* * EGCS-style stack adjust: * * subq sp, 64, sp */ CHECK_FRAMESIZE; pi->pi_frame_size += ins.operate_lit_format.literal; } else if (ins.mem_format.opcode == op_stq && ins.mem_format.rs == 30 && ins.mem_format.rd != 31) { /* Store of (non-zero) register onto the stack. */ signed_immediate = (long)ins.mem_format.displacement; pi->pi_regmask |= 1 << ins.mem_format.rd; pi->pi_reg_offset[ins.mem_format.rd] = signed_immediate; } } return (0); } static int sym_is_trapsymbol(uintptr_t v) { int i; for (i = 0; special_symbols[i].ss_val != 0; ++i) if (v == special_symbols[i].ss_val) return 1; return 0; } static void -decode_syscall(int number, struct proc *p) +decode_syscall(int number, struct thread *td) { + struct proc *p; c_db_sym_t sym; db_expr_t diff; sy_call_t *f; const char *symname; + p = (td != NULL) ? td->td_proc : NULL; db_printf(" (%d", number); if (p != NULL && 0 <= number && number < p->p_sysent->sv_size) { f = p->p_sysent->sv_table[number].sy_call; sym = db_search_symbol((db_addr_t)f, DB_STGY_ANY, &diff); if (sym != DB_SYM_NULL && diff == 0) { db_symbol_values(sym, &symname, NULL); db_printf(", %s, %s", p->p_sysent->sv_name, symname); } } db_printf(")"); } -void -db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *modif) +static int +db_backtrace(struct thread *td, db_addr_t frame, db_addr_t pc, int count) { - db_addr_t callpc = 0, frame = 0, symval; struct prologue_info pi; - db_expr_t diff; + struct trapframe *tf; + const char *symname; c_db_sym_t sym; + db_expr_t diff; + db_addr_t symval; + u_long last_ipl, tfps; int i; - u_long tfps; - const char *symname; - struct pcb *pcbp; - struct trapframe *tf = NULL; - boolean_t ra_from_tf = FALSE; - boolean_t ra_from_pcb; - u_long last_ipl = ~0L; - struct proc *p = NULL; - struct thread *td = NULL; - boolean_t have_trapframe = FALSE; - pid_t pid; if (count == -1) - count = 65535; + count = 1024; - if (!have_addr) { - td = curthread; - p = td->td_proc; - addr = DDB_REGS->tf_regs[FRAME_SP] - FRAME_SIZE * 8; - tf = (struct trapframe *)addr; - have_trapframe = 1; - } else if (addr < KERNBASE) { - pid = (addr % 16) + ((addr >> 4) % 16) * 10 + - ((addr >> 8) % 16) * 100 + ((addr >> 12) % 16) * 1000 + - ((addr >> 16) % 16) * 10000; - /* - * The pcb for curproc is not valid at this point, - * so fall back to the default case. - */ - if (pid == curthread->td_proc->p_pid) { - td = curthread; - p = td->td_proc; - addr = DDB_REGS->tf_regs[FRAME_SP] - FRAME_SIZE * 8; - tf = (struct trapframe *)addr; - have_trapframe = 1; - } else { - /* sx_slock(&allproc_lock); */ - LIST_FOREACH(p, &allproc, p_list) { - if (p->p_pid == pid) - break; - } - /* sx_sunlock(&allproc_lock); */ - if (p == NULL) { - db_printf("pid %d not found\n", pid); - return; - } - if ((p->p_sflag & PS_INMEM) == 0) { - db_printf("pid %d swapped out\n", pid); - return; - } - pcbp = FIRST_THREAD_IN_PROC(p)->td_pcb; /* XXXKSE */ - addr = (db_expr_t)pcbp->pcb_hw.apcb_ksp; - callpc = pcbp->pcb_context[7]; - frame = addr; - } - } else { - struct trace_request *tr; - - tr = (struct trace_request *)addr; - if (tr->ksp < KERNBASE || tr->pc < KERNBASE) { - db_printf("alpha trace requires known PC =eject=\n"); - return; - } - callpc = tr->pc; - addr = tr->ksp; - frame = addr; - } - + last_ipl = ~0L; + tf = NULL; while (count--) { - if (have_trapframe) { - frame = (db_addr_t)tf + FRAME_SIZE * 8; - callpc = tf->tf_regs[FRAME_PC]; - ra_from_tf = TRUE; - have_trapframe = 0; - } - sym = db_search_symbol(callpc, DB_STGY_ANY, &diff); + sym = db_search_symbol(pc, DB_STGY_ANY, &diff); if (sym == DB_SYM_NULL) - break; + return (ENOENT); db_symbol_values(sym, &symname, (db_expr_t *)&symval); - if (callpc < symval) { - db_printf("symbol botch: callpc 0x%lx < " - "func 0x%lx (%s)\n", callpc, symval, symname); - return; + if (pc < symval) { + db_printf("symbol botch: pc 0x%lx < " + "func 0x%lx (%s)\n", pc, symval, symname); + return (0); } /* * XXX Printing out arguments is Hard. We'd have to * keep lots of state as we traverse the frame, figuring * out where the arguments to the function are stored * on the stack. * * Even worse, they may be stored to the stack _after_ * being modified in place; arguments are passed in * registers. * * So, in order for this to work reliably, we pretty much * have to have a kernel built with `cc -g': * * - The debugging symbols would tell us where the * arguments are, how many there are, if there were * any passed on the stack, etc. * * - Presumably, the compiler would be careful to * store the argument registers on the stack before * modifying the registers, so that a debugger could * know what those values were upon procedure entry. * * Because of this, we don't bother. We've got most of the * benefit of back tracking without the arguments, and we * could get the arguments if we use a remote source-level * debugger (for serious debugging). */ db_printf("%s() at ", symname); - db_printsym(callpc, DB_STGY_PROC); + db_printsym(pc, DB_STGY_PROC); db_printf("\n"); /* * If we are in a trap vector, frame points to a * trapframe. */ if (sym_is_trapsymbol(symval)) { tf = (struct trapframe *)frame; - for (i = 0; special_symbols[i].ss_val != 0; ++i) if (symval == special_symbols[i].ss_val) db_printf("--- %s", special_symbols[i].ss_note); tfps = tf->tf_regs[FRAME_PS]; if (symval == (uintptr_t)&XentSys) - decode_syscall(tf->tf_regs[FRAME_V0], p); + decode_syscall(tf->tf_regs[FRAME_V0], td); if ((tfps & ALPHA_PSL_IPL_MASK) != last_ipl) { last_ipl = tfps & ALPHA_PSL_IPL_MASK; if (symval != (uintptr_t)&XentSys) db_printf(" (from ipl %ld)", last_ipl); } db_printf(" ---\n"); if (tfps & ALPHA_PSL_USERMODE) { db_printf("--- user mode ---\n"); break; /* Terminate search. */ } - have_trapframe = 1; + frame = (db_addr_t)(tf + 1); + pc = tf->tf_regs[FRAME_PC]; continue; } /* * This is a bit trickier; we must decode the function * prologue to find the saved RA. * * XXX How does this interact w/ alloca()?! */ - if (decode_prologue(callpc, symval, &pi)) - return; + if (decode_prologue(pc, symval, &pi)) + return (0); if ((pi.pi_regmask & (1 << 26)) == 0) { /* * No saved RA found. We might have RA from * the trap frame, however (e.g trap occurred * in a leaf call). If not, we've found the * root of the call graph. */ - if (ra_from_tf) - callpc = tf->tf_regs[FRAME_RA]; + if (tf) + pc = tf->tf_regs[FRAME_RA]; else { db_printf("--- root of call graph ---\n"); break; } } else - callpc = *(u_long *)(frame + pi.pi_reg_offset[26]); - ra_from_tf = ra_from_pcb = FALSE; -#if 0 - /* - * The call was actually made at RA - 4; the PC is - * updated before being stored in RA. - */ - callpc -= 4; -#endif + pc = *(u_long *)(frame + pi.pi_reg_offset[26]); frame += pi.pi_frame_size; + tf = NULL; } + + return (0); } void -db_print_backtrace(void) +db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, + char *modif) { - struct trace_request tr; + struct thread *td; + td = (have_addr) ? kdb_thr_lookup(addr) : kdb_thread; + if (td == NULL) { + db_printf("Thread %d not found\n", (int)addr); + return; + } + db_trace_thread(td, count); +} + +void +db_trace_self(void) +{ + register_t pc, sp; + __asm __volatile( " mov $30,%0 \n" " lda %1,1f \n" "1:\n" - : "=r" (tr.ksp), "=r" (tr.pc)); - db_stack_trace_cmd((db_addr_t)&tr, 1, -1, NULL); + : "=r" (sp), "=r" (pc)); + db_backtrace(curthread, sp, pc, -1); +} + +int +db_trace_thread(struct thread *thr, int count) +{ + struct pcb *ctx; + + ctx = kdb_thr_ctx(thr); + return (db_backtrace(thr, ctx->pcb_hw.apcb_ksp, ctx->pcb_context[7], + count)); } int db_md_set_watchpoint(addr, size) db_expr_t addr; db_expr_t size; { return (-1); } int db_md_clr_watchpoint(addr, size) db_expr_t addr; db_expr_t size; { return (-1); } void db_md_list_watchpoints() { return; } Index: head/sys/alpha/include/db_machdep.h =================================================================== --- head/sys/alpha/include/db_machdep.h (revision 131951) +++ head/sys/alpha/include/db_machdep.h (revision 131952) @@ -1,117 +1,100 @@ /* $FreeBSD$ */ /* $NetBSD: db_machdep.h,v 1.6 1997/09/06 02:02:25 thorpej Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. * All rights reserved. * * Author: Chris G. Demetriou * * 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 the * rights to redistribute these changes. */ #ifndef _ALPHA_DB_MACHDEP_H_ #define _ALPHA_DB_MACHDEP_H_ -/* - * Machine-dependent defines for new kernel debugger. - */ -#ifndef KLD_MODULE -#include "opt_ddb.h" -#endif - #include #include #include -#define DB_NO_AOUT +#define DB_NO_AOUT typedef vm_offset_t db_addr_t; /* address - unsigned */ typedef long db_expr_t; /* expression - signed */ -typedef struct trapframe db_regs_t; -#ifdef DDB -extern db_regs_t ddb_regs; /* register state */ -#endif -#define DDB_REGS (&ddb_regs) +#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_context[7]) -#define PC_REGS(regs) ((db_addr_t)(regs)->tf_regs[FRAME_PC]) - #define BKPT_INST 0x00000080 /* breakpoint instruction */ #define BKPT_SIZE (4) /* size of breakpoint inst */ #define BKPT_SET(inst) (BKPT_INST) -#define FIXUP_PC_AFTER_BREAK \ - (ddb_regs.tf_regs[FRAME_PC] -= BKPT_SIZE); +#define FIXUP_PC_AFTER_BREAK (kdb_frame->tf_regs[FRAME_PC] -= BKPT_SIZE); #define SOFTWARE_SSTEP 1 /* no hardware support */ -#define IS_BREAKPOINT_TRAP(type, code) ((type) == ALPHA_KENTRY_IF && \ - (code) == ALPHA_IF_CODE_BPT) + +#define IS_BREAKPOINT_TRAP(type, code) \ + ((type) == ALPHA_KENTRY_IF && (code) == ALPHA_IF_CODE_BPT) #define IS_WATCHPOINT_TRAP(type, code) 0 /* * Functions needed for software single-stepping. */ +boolean_t db_inst_trap_return(int inst); +boolean_t db_inst_return(int inst); +boolean_t db_inst_call(int inst); +boolean_t db_inst_branch(int inst); +boolean_t db_inst_load(int inst); +boolean_t db_inst_store(int inst); +boolean_t db_inst_unconditional_flow_transfer(int inst); +db_addr_t db_branch_taken(int inst, db_addr_t pc); -boolean_t db_inst_trap_return(int inst); -boolean_t db_inst_return(int inst); -boolean_t db_inst_call(int inst); -boolean_t db_inst_branch(int inst); -boolean_t db_inst_load(int inst); -boolean_t db_inst_store(int inst); -boolean_t db_inst_unconditional_flow_transfer(int inst); -db_addr_t db_branch_taken(int inst, db_addr_t pc, db_regs_t *regs); - #define inst_trap_return(ins) db_inst_trap_return(ins) #define inst_return(ins) db_inst_return(ins) #define inst_call(ins) db_inst_call(ins) #define inst_branch(ins) db_inst_branch(ins) #define inst_load(ins) db_inst_load(ins) #define inst_store(ins) db_inst_store(ins) #define inst_unconditional_flow_transfer(ins) \ db_inst_unconditional_flow_transfer(ins) -#define branch_taken(ins, pc, regs) \ - db_branch_taken((ins), (pc), (regs)) +#define branch_taken(ins, pc) db_branch_taken(ins, pc) /* No delay slots on Alpha. */ #define next_instr_address(v, b) ((db_addr_t) ((b) ? (v) : ((v) + 4))) -u_long db_register_value(db_regs_t *, int); -int kdb_trap(unsigned long, unsigned long, unsigned long, - unsigned long, struct trapframe *); +u_long db_register_value(int); /* * Pretty arbitrary */ #define DB_SMALL_VALUE_MAX 0x7fffffff #define DB_SMALL_VALUE_MIN (-0x400001) /* * We define some of our own commands. */ #define DB_MACHINE_COMMANDS /* * We use Elf64 symbols in DDB. */ #define DB_ELFSIZE 64 #endif /* _ALPHA_DB_MACHDEP_H_ */ Index: head/sys/amd64/amd64/db_interface.c =================================================================== --- head/sys/amd64/amd64/db_interface.c (revision 131951) +++ head/sys/amd64/amd64/db_interface.c (revision 131952) @@ -1,335 +1,147 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. */ #include __FBSDID("$FreeBSD$"); /* * Interface to new debugger. */ #include #include +#include #include #include #include #include #include #include #include #include #include -#include - -static jmp_buf *db_nofault = 0; -extern jmp_buf db_jmpbuf; - -extern void gdb_handle_exception(db_regs_t *, int, int); - -int db_active; -db_regs_t ddb_regs; - -static jmp_buf db_global_jmpbuf; - /* - * kdb_trap - field a TRACE or BPT trap + * Read bytes from kernel address space for debugger. */ int -kdb_trap(int type, int code, struct amd64_saved_state *regs) +db_read_bytes(vm_offset_t addr, size_t size, char *data) { - u_long ef; - volatile int ddb_mode = !(boothowto & RB_GDB); + jmp_buf jb; + void *prev_jb; + char *src; + int ret; - /* - * XXX try to do nothing if the console is in graphics mode. - * Handle trace traps (and hardware breakpoints...) by ignoring - * them except for forgetting about them. Return 0 for other - * traps to say that we haven't done anything. The trap handler - * will usually panic. We should handle breakpoint traps for - * our breakpoints by disarming our breakpoints and fixing up - * %eip. - */ - if (cnunavailable() != 0 && ddb_mode) { - if (type == T_TRCTRAP) { - regs->tf_rflags &= ~PSL_T; - return (1); - } - return (0); + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + src = (char *)addr; + while (size-- > 0) + *data++ = *src++; } - - ef = read_rflags(); - disable_intr(); - -#ifdef SMP - -#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf("\nCPU%d stopping CPUs: 0x%08x...", PCPU_GET(cpuid), - PCPU_GET(other_cpus)); -#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ - - /* We stop all CPUs except ourselves (obviously) */ - stop_cpus(PCPU_GET(other_cpus)); - -#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf(" stopped.\n"); -#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ - -#endif /* SMP */ - - switch (type) { - case T_BPTFLT: /* breakpoint */ - case T_TRCTRAP: /* debug exception */ - break; - - default: - /* - * XXX this is almost useless now. In most cases, - * trap_fatal() has already printed a much more verbose - * message. However, it is dangerous to print things in - * trap_fatal() - printf() might be reentered and trap. - * The debugger should be given control first. - */ - if (ddb_mode) - db_printf("kernel: type %d trap, code=%x\n", type, code); - - if (db_nofault) { - jmp_buf *no_fault = db_nofault; - db_nofault = 0; - longjmp(*no_fault, 1); - } - } - - /* - * This handles unexpected traps in ddb commands, including calls to - * non-ddb functions. db_nofault only applies to memory accesses by - * internal ddb commands. - */ - if (db_active) - longjmp(db_global_jmpbuf, 1); - - /* - * XXX We really should switch to a local stack here. - */ - ddb_regs = *regs; - - /* - * If in kernel mode, esp and ss are not saved, so dummy them up. - */ - if (ISPL(regs->tf_cs) == 0) { - ddb_regs.tf_rsp = (long)®s->tf_rsp; - ddb_regs.tf_ss = rss(); - } - - (void) setjmp(db_global_jmpbuf); - if (ddb_mode) { - if (!db_active) - cndbctl(TRUE); - db_active = 1; - db_trap(type, code); - cndbctl(FALSE); - } else { - db_active = 1; - gdb_handle_exception(&ddb_regs, type, code); - } - db_active = 0; - - regs->tf_rip = ddb_regs.tf_rip; - regs->tf_rflags = ddb_regs.tf_rflags; - regs->tf_rax = ddb_regs.tf_rax; - regs->tf_rcx = ddb_regs.tf_rcx; - regs->tf_rdx = ddb_regs.tf_rdx; - regs->tf_rbx = ddb_regs.tf_rbx; - - /* - * If in user mode, the saved ESP and SS were valid, restore them. - */ - if (ISPL(regs->tf_cs)) { - regs->tf_rsp = ddb_regs.tf_rsp; - regs->tf_ss = ddb_regs.tf_ss & 0xffff; - } - - regs->tf_rbp = ddb_regs.tf_rbp; - regs->tf_rsi = ddb_regs.tf_rsi; - regs->tf_rdi = ddb_regs.tf_rdi; - - regs->tf_r8 = ddb_regs.tf_r8; - regs->tf_r9 = ddb_regs.tf_r9; - regs->tf_r10 = ddb_regs.tf_r10; - regs->tf_r11 = ddb_regs.tf_r11; - regs->tf_r12 = ddb_regs.tf_r12; - regs->tf_r13 = ddb_regs.tf_r13; - regs->tf_r14 = ddb_regs.tf_r14; - regs->tf_r15 = ddb_regs.tf_r15; - -#if 0 - regs->tf_es = ddb_regs.tf_es & 0xffff; - regs->tf_fs = ddb_regs.tf_fs & 0xffff; -#endif - regs->tf_cs = ddb_regs.tf_cs & 0xffff; -#if 0 - regs->tf_ds = ddb_regs.tf_ds & 0xffff; -#endif - -#ifdef SMP - -#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf("\nCPU%d restarting CPUs: 0x%08x...", PCPU_GET(cpuid), - stopped_cpus); -#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ - - /* Restart all the CPUs we previously stopped */ - if (stopped_cpus != PCPU_GET(other_cpus) && smp_started != 0) { - db_printf("whoa, other_cpus: 0x%08x, stopped_cpus: 0x%08x\n", - PCPU_GET(other_cpus), stopped_cpus); - panic("stop_cpus() failed"); - } - restart_cpus(stopped_cpus); - -#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf(" restarted.\n"); -#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ - -#endif /* SMP */ - - write_rflags(ef); - - return (1); + (void)kdb_jmpbuf(prev_jb); + return (ret); } /* - * Read bytes from kernel address space for debugger. - */ -void -db_read_bytes(vm_offset_t addr, size_t size, char *data) -{ - char *src; - - db_nofault = &db_jmpbuf; - - src = (char *)addr; - while (size-- > 0) - *data++ = *src++; - - db_nofault = 0; -} - -/* * Write bytes to kernel address space for debugger. */ -void +int db_write_bytes(vm_offset_t addr, size_t size, char *data) { - char *dst; - + jmp_buf jb; + void *prev_jb; + char *dst; pt_entry_t *ptep0 = NULL; pt_entry_t oldmap0 = 0; vm_offset_t addr1; pt_entry_t *ptep1 = NULL; pt_entry_t oldmap1 = 0; + int ret; - db_nofault = &db_jmpbuf; + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + if (addr > trunc_page((vm_offset_t)btext) - size && + addr < round_page((vm_offset_t)etext)) { - if (addr > trunc_page((vm_offset_t)btext) - size && - addr < round_page((vm_offset_t)etext)) { + ptep0 = vtopte(addr); + oldmap0 = *ptep0; + *ptep0 |= PG_RW; - ptep0 = vtopte(addr); - oldmap0 = *ptep0; - *ptep0 |= PG_RW; + /* + * Map another page if the data crosses a page + * boundary. + */ + if ((*ptep0 & PG_PS) == 0) { + addr1 = trunc_page(addr + size - 1); + if (trunc_page(addr) != addr1) { + ptep1 = vtopte(addr1); + oldmap1 = *ptep1; + *ptep1 |= PG_RW; + } + } else { + addr1 = trunc_2mpage(addr + size - 1); + if (trunc_2mpage(addr) != addr1) { + ptep1 = vtopte(addr1); + oldmap1 = *ptep1; + *ptep1 |= PG_RW; + } + } - /* Map another page if the data crosses a page boundary. */ - if ((*ptep0 & PG_PS) == 0) { - addr1 = trunc_page(addr + size - 1); - if (trunc_page(addr) != addr1) { - ptep1 = vtopte(addr1); - oldmap1 = *ptep1; - *ptep1 |= PG_RW; - } - } else { - addr1 = trunc_2mpage(addr + size - 1); - if (trunc_2mpage(addr) != addr1) { - ptep1 = vtopte(addr1); - oldmap1 = *ptep1; - *ptep1 |= PG_RW; + invltlb(); } - } - invltlb(); + dst = (char *)addr; + + while (size-- > 0) + *dst++ = *data++; } - dst = (char *)addr; + (void)kdb_jmpbuf(prev_jb); - while (size-- > 0) - *dst++ = *data++; - - db_nofault = 0; - if (ptep0) { - *ptep0 = oldmap0; + *ptep0 = oldmap0; - if (ptep1) - *ptep1 = oldmap1; + if (ptep1) + *ptep1 = oldmap1; - invltlb(); + invltlb(); } -} -/* - * XXX - * Move this to machdep.c and allow it to be called if any debugger is - * installed. - */ -void -Debugger(const char *msg) -{ - static volatile u_int in_Debugger; - - /* - * XXX - * Do nothing if the console is in graphics mode. This is - * OK if the call is for the debugger hotkey but not if the call - * is a weak form of panicing. - */ - if (cnunavailable() != 0 && !(boothowto & RB_GDB)) - return; - - if (atomic_cmpset_acq_int(&in_Debugger, 0, 1)) { - db_printf("Debugger(\"%s\")\n", msg); - breakpoint(); - atomic_store_rel_int(&in_Debugger, 0); - } + return (ret); } void db_show_mdpcpu(struct pcpu *pc) { #if 0 db_printf("currentldt = 0x%x\n", pc->pc_currentldt); #endif } Index: head/sys/amd64/amd64/db_trace.c =================================================================== --- head/sys/amd64/amd64/db_trace.c (revision 131951) +++ head/sys/amd64/amd64/db_trace.c (revision 131952) @@ -1,719 +1,685 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. */ #include __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include -db_varfcn_t db_dr0; -db_varfcn_t db_dr1; -db_varfcn_t db_dr2; -db_varfcn_t db_dr3; -db_varfcn_t db_dr4; -db_varfcn_t db_dr5; -db_varfcn_t db_dr6; -db_varfcn_t db_dr7; +static db_varfcn_t db_dr0; +static db_varfcn_t db_dr1; +static db_varfcn_t db_dr2; +static db_varfcn_t db_dr3; +static db_varfcn_t db_dr4; +static db_varfcn_t db_dr5; +static db_varfcn_t db_dr6; +static db_varfcn_t db_dr7; +static db_varfcn_t db_frame; +static db_varfcn_t db_rsp; +static db_varfcn_t db_ss; /* * Machine register set. */ +#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) struct db_variable db_regs[] = { - { "cs", &ddb_regs.tf_cs, FCN_NULL }, + { "cs", DB_OFFSET(tf_cs), db_frame }, #if 0 - { "ds", &ddb_regs.tf_ds, FCN_NULL }, - { "es", &ddb_regs.tf_es, FCN_NULL }, - { "fs", &ddb_regs.tf_fs, FCN_NULL }, - { "gs", &ddb_regs.tf_gs, FCN_NULL }, + { "ds", DB_OFFSET(tf_ds), db_frame }, + { "es", DB_OFFSET(tf_es), db_frame }, + { "fs", DB_OFFSET(tf_fs), db_frame }, + { "gs", DB_OFFSET(tf_gs), db_frame }, #endif - { "ss", &ddb_regs.tf_ss, FCN_NULL }, - { "rax", &ddb_regs.tf_rax, FCN_NULL }, - { "rcx", &ddb_regs.tf_rcx, FCN_NULL }, - { "rdx", &ddb_regs.tf_rdx, FCN_NULL }, - { "rbx", &ddb_regs.tf_rbx, FCN_NULL }, - { "rsp", &ddb_regs.tf_rsp, FCN_NULL }, - { "rbp", &ddb_regs.tf_rbp, FCN_NULL }, - { "rsi", &ddb_regs.tf_rsi, FCN_NULL }, - { "rdi", &ddb_regs.tf_rdi, FCN_NULL }, - { "r8", &ddb_regs.tf_r8, FCN_NULL }, - { "r9", &ddb_regs.tf_r9, FCN_NULL }, - { "r10", &ddb_regs.tf_r10, FCN_NULL }, - { "r11", &ddb_regs.tf_r11, FCN_NULL }, - { "r12", &ddb_regs.tf_r12, FCN_NULL }, - { "r13", &ddb_regs.tf_r13, FCN_NULL }, - { "r14", &ddb_regs.tf_r14, FCN_NULL }, - { "r15", &ddb_regs.tf_r15, FCN_NULL }, - { "rip", &ddb_regs.tf_rip, FCN_NULL }, - { "rflags", &ddb_regs.tf_rflags, FCN_NULL }, - { "dr0", NULL, db_dr0 }, - { "dr1", NULL, db_dr1 }, - { "dr2", NULL, db_dr2 }, - { "dr3", NULL, db_dr3 }, - { "dr4", NULL, db_dr4 }, - { "dr5", NULL, db_dr5 }, - { "dr6", NULL, db_dr6 }, - { "dr7", NULL, db_dr7 }, + { "ss", NULL, db_ss }, + { "rax", DB_OFFSET(tf_rax), db_frame }, + { "rcx", DB_OFFSET(tf_rcx), db_frame }, + { "rdx", DB_OFFSET(tf_rdx), db_frame }, + { "rbx", DB_OFFSET(tf_rbx), db_frame }, + { "rsp", NULL, db_rsp }, + { "rbp", DB_OFFSET(tf_rbp), db_frame }, + { "rsi", DB_OFFSET(tf_rsi), db_frame }, + { "rdi", DB_OFFSET(tf_rdi), db_frame }, + { "r8", DB_OFFSET(tf_r8), db_frame }, + { "r9", DB_OFFSET(tf_r9), db_frame }, + { "r10", DB_OFFSET(tf_r10), db_frame }, + { "r11", DB_OFFSET(tf_r11), db_frame }, + { "r12", DB_OFFSET(tf_r12), db_frame }, + { "r13", DB_OFFSET(tf_r13), db_frame }, + { "r14", DB_OFFSET(tf_r14), db_frame }, + { "r15", DB_OFFSET(tf_r15), db_frame }, + { "rip", DB_OFFSET(tf_rip), db_frame }, + { "rflags", DB_OFFSET(tf_rflags), db_frame }, + { "dr0", NULL, db_dr0 }, + { "dr1", NULL, db_dr1 }, + { "dr2", NULL, db_dr2 }, + { "dr3", NULL, db_dr3 }, + { "dr4", NULL, db_dr4 }, + { "dr5", NULL, db_dr5 }, + { "dr6", NULL, db_dr6 }, + { "dr7", NULL, db_dr7 }, }; struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); +#define DB_DRX_FUNC(reg) \ +static int \ +db_ ## reg (vp, valuep, op) \ + struct db_variable *vp; \ + db_expr_t * valuep; \ + int op; \ +{ \ + if (op == DB_VAR_GET) \ + *valuep = r ## reg (); \ + else \ + load_ ## reg (*valuep); \ + return (1); \ +} + +DB_DRX_FUNC(dr0) +DB_DRX_FUNC(dr1) +DB_DRX_FUNC(dr2) +DB_DRX_FUNC(dr3) +DB_DRX_FUNC(dr4) +DB_DRX_FUNC(dr5) +DB_DRX_FUNC(dr6) +DB_DRX_FUNC(dr7) + +static __inline long +get_rsp(struct trapframe *tf) +{ + return ((ISPL(tf->tf_cs)) ? tf->tf_rsp : + (db_expr_t)tf + offsetof(struct trapframe, tf_rsp)); +} + +static int +db_frame(struct db_variable *vp, db_expr_t *valuep, int op) +{ + long *reg; + + if (kdb_frame == NULL) + return (0); + + reg = (long *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep); + if (op == DB_VAR_GET) + *valuep = *reg; + else + *reg = *valuep; + return (1); +} + +static int +db_rsp(struct db_variable *vp, db_expr_t *valuep, int op) +{ + + if (kdb_frame == NULL) + return (0); + + if (op == DB_VAR_GET) + *valuep = get_rsp(kdb_frame); + else if (ISPL(kdb_frame->tf_cs)) + kdb_frame->tf_rsp = *valuep; + return (1); +} + +static int +db_ss(struct db_variable *vp, db_expr_t *valuep, int op) +{ + + if (kdb_frame == NULL) + return (0); + + if (op == DB_VAR_GET) + *valuep = (ISPL(kdb_frame->tf_cs)) ? kdb_frame->tf_ss : rss(); + else if (ISPL(kdb_frame->tf_cs)) + kdb_frame->tf_ss = *valuep; + return (1); +} + /* * Stack trace. */ #define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK) struct amd64_frame { struct amd64_frame *f_frame; long f_retaddr; long f_arg0; }; #define NORMAL 0 #define TRAP 1 #define INTERRUPT 2 #define SYSCALL 3 -static void db_nextframe(struct amd64_frame **, db_addr_t *, struct proc *); +static void db_nextframe(struct amd64_frame **, db_addr_t *, struct thread *); static int db_numargs(struct amd64_frame *); static void db_print_stack_entry(const char *, int, char **, long *, db_addr_t); -static void decode_syscall(int, struct proc *); -static void db_trace_one_stack(int count, boolean_t have_addr, - struct proc *p, struct amd64_frame *frame, db_addr_t callpc); +static void decode_syscall(int, struct thread *); - static char * watchtype_str(int type); int amd64_set_watch(int watchnum, unsigned int watchaddr, int size, int access, struct dbreg * d); int amd64_clr_watch(int watchnum, struct dbreg * d); int db_md_set_watchpoint(db_expr_t addr, db_expr_t size); int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size); void db_md_list_watchpoints(void); - /* * Figure out how many arguments were passed into the frame at "fp". */ static int db_numargs(fp) struct amd64_frame *fp; { #if 1 return (0); /* regparm, needs dwarf2 info */ #else long *argp; int inst; int args; argp = (long *)db_get_value((long)&fp->f_retaddr, 8, FALSE); /* * XXX etext is wrong for LKMs. We should attempt to interpret * the instruction at the return address in all cases. This * may require better fault handling. */ if (argp < (long *)btext || argp >= (long *)etext) { args = 5; } else { inst = db_get_value((long)argp, 4, FALSE); if ((inst & 0xff) == 0x59) /* popl %ecx */ args = 1; else if ((inst & 0xffff) == 0xc483) /* addl $Ibs, %esp */ args = ((inst >> 16) & 0xff) / 4; else args = 5; } return (args); #endif } static void db_print_stack_entry(name, narg, argnp, argp, callpc) const char *name; int narg; char **argnp; long *argp; db_addr_t callpc; { db_printf("%s(", name); #if 0 while (narg) { if (argnp) db_printf("%s=", *argnp++); db_printf("%lr", (long)db_get_value((long)argp, 8, FALSE)); argp++; if (--narg != 0) db_printf(","); } #endif db_printf(") at "); db_printsym(callpc, DB_STGY_PROC); db_printf("\n"); } static void -decode_syscall(number, p) - int number; - struct proc *p; +decode_syscall(int number, struct thread *td) { + struct proc *p; c_db_sym_t sym; db_expr_t diff; sy_call_t *f; const char *symname; db_printf(" (%d", number); + p = (td != NULL) ? td->td_proc : NULL; if (p != NULL && 0 <= number && number < p->p_sysent->sv_size) { f = p->p_sysent->sv_table[number].sy_call; sym = db_search_symbol((db_addr_t)f, DB_STGY_ANY, &diff); if (sym != DB_SYM_NULL && diff == 0) { db_symbol_values(sym, &symname, NULL); db_printf(", %s, %s", p->p_sysent->sv_name, symname); } } db_printf(")"); } /* * Figure out the next frame up in the call stack. */ static void -db_nextframe(fp, ip, p) - struct amd64_frame **fp; /* in/out */ - db_addr_t *ip; /* out */ - struct proc *p; /* in */ +db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td) { struct trapframe *tf; int frame_type; long rip, rsp, rbp; db_expr_t offset; c_db_sym_t sym; const char *name; rip = db_get_value((long) &(*fp)->f_retaddr, 8, FALSE); rbp = db_get_value((long) &(*fp)->f_frame, 8, FALSE); /* * Figure out frame type. */ frame_type = NORMAL; sym = db_search_symbol(rip, DB_STGY_ANY, &offset); db_symbol_values(sym, &name, NULL); if (name != NULL) { if (strcmp(name, "calltrap") == 0 || strcmp(name, "fork_trampoline") == 0) frame_type = TRAP; else if (strncmp(name, "Xatpic_intr", 11) == 0 || strncmp(name, "Xatpic_fastintr", 15) == 0 || strncmp(name, "Xapic_isr", 9) == 0) frame_type = INTERRUPT; else if (strcmp(name, "Xfast_syscall") == 0) frame_type = SYSCALL; } /* * Normal frames need no special processing. */ if (frame_type == NORMAL) { *ip = (db_addr_t) rip; *fp = (struct amd64_frame *) rbp; return; } db_print_stack_entry(name, 0, 0, 0, rip); /* * Point to base of trapframe which is just above the * current frame. */ tf = (struct trapframe *)((long)*fp + 16); if (INKERNEL((long) tf)) { - rsp = (ISPL(tf->tf_cs) == SEL_UPL) ? - tf->tf_rsp : (long)&tf->tf_rsp; + rsp = get_rsp(tf); rip = tf->tf_rip; rbp = tf->tf_rbp; switch (frame_type) { case TRAP: db_printf("--- trap %#lr", tf->tf_trapno); break; case SYSCALL: db_printf("--- syscall"); - decode_syscall(tf->tf_rax, p); + decode_syscall(tf->tf_rax, td); break; case INTERRUPT: db_printf("--- interrupt"); break; default: panic("The moon has moved again."); } db_printf(", rip = %#lr, rsp = %#lr, rbp = %#lr ---\n", rip, rsp, rbp); } *ip = (db_addr_t) rip; *fp = (struct amd64_frame *) rbp; } -void -db_stack_trace_cmd(addr, have_addr, count, modif) - db_expr_t addr; - boolean_t have_addr; - db_expr_t count; - char *modif; +static int +db_backtrace(struct thread *td, struct trapframe *tf, + struct amd64_frame *frame, db_addr_t pc, int count) { - struct amd64_frame *frame; - struct proc *p; - struct pcb *pcb; - struct thread *td; - db_addr_t callpc; - pid_t pid; + struct amd64_frame *actframe; +#define MAXNARG 16 + char *argnames[MAXNARG], **argnp = NULL; + const char *name; + long *argp; + db_expr_t offset; + c_db_sym_t sym; + int narg; + boolean_t first; if (count == -1) count = 1024; - if (!have_addr) { - td = curthread; - p = td->td_proc; - frame = (struct amd64_frame *)ddb_regs.tf_rbp; - if (frame == NULL) - frame = (struct amd64_frame *)(ddb_regs.tf_rsp - 8); - callpc = (db_addr_t)ddb_regs.tf_rip; - } else if (!INKERNEL(addr)) { - pid = (addr % 16) + ((addr >> 4) % 16) * 10 + - ((addr >> 8) % 16) * 100 + ((addr >> 12) % 16) * 1000 + - ((addr >> 16) % 16) * 10000; - /* - * The pcb for curproc is not valid at this point, - * so fall back to the default case. - */ - if (pid == curthread->td_proc->p_pid) { - td = curthread; - p = td->td_proc; - frame = (struct amd64_frame *)ddb_regs.tf_rbp; - if (frame == NULL) - frame = (struct amd64_frame *) - (ddb_regs.tf_rsp - 8); - callpc = (db_addr_t)ddb_regs.tf_rip; - } else { - - /* sx_slock(&allproc_lock); */ - LIST_FOREACH(p, &allproc, p_list) { - if (p->p_pid == pid) - break; - } - /* sx_sunlock(&allproc_lock); */ - if (p == NULL) { - db_printf("pid %d not found\n", pid); - return; - } - if ((p->p_sflag & PS_INMEM) == 0) { - db_printf("pid %d swapped out\n", pid); - return; - } - pcb = FIRST_THREAD_IN_PROC(p)->td_pcb; /* XXXKSE */ - frame = (struct amd64_frame *)pcb->pcb_rbp; - if (frame == NULL) - frame = (struct amd64_frame *) - (pcb->pcb_rsp - 8); - callpc = (db_addr_t)pcb->pcb_rip; - } - } else { - p = NULL; - frame = (struct amd64_frame *)addr; - callpc = (db_addr_t)db_get_value((long)&frame->f_retaddr, 8, FALSE); - frame = frame->f_frame; - } - db_trace_one_stack(count, have_addr, p, frame, callpc); -} - -void -db_stack_thread(db_expr_t addr, boolean_t have_addr, - db_expr_t count, char *modif) -{ - struct amd64_frame *frame; - struct thread *td; - struct proc *p; - struct pcb *pcb; - db_addr_t callpc; - - if (!have_addr) - return; - if (!INKERNEL(addr)) { - printf("bad thread address"); - return; - } - td = (struct thread *)addr; - /* quick sanity check */ - if ((p = td->td_proc) != td->td_ksegrp->kg_proc) - return; - if (TD_IS_SWAPPED(td)) { - db_printf("thread at %p swapped out\n", td); - return; - } - if (td == curthread) { - frame = (struct amd64_frame *)ddb_regs.tf_rbp; - if (frame == NULL) - frame = (struct amd64_frame *)(ddb_regs.tf_rsp - 8); - callpc = (db_addr_t)ddb_regs.tf_rip; - } else { - pcb = td->td_pcb; - frame = (struct amd64_frame *)pcb->pcb_rbp; - if (frame == NULL) - frame = (struct amd64_frame *) (pcb->pcb_rsp - 8); - callpc = (db_addr_t)pcb->pcb_rip; - } - db_trace_one_stack(count, have_addr, p, frame, callpc); -} - -static void -db_trace_one_stack(int count, boolean_t have_addr, - struct proc *p, struct amd64_frame *frame, db_addr_t callpc) -{ - long *argp; - boolean_t first; - first = TRUE; while (count--) { - struct amd64_frame *actframe; - int narg; - const char * name; - db_expr_t offset; - c_db_sym_t sym; -#define MAXNARG 16 - char *argnames[MAXNARG], **argnp = NULL; - - sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); + sym = db_search_symbol(pc, DB_STGY_ANY, &offset); db_symbol_values(sym, &name, NULL); /* * Attempt to determine a (possibly fake) frame that gives * the caller's pc. It may differ from `frame' if the * current function never sets up a standard frame or hasn't * set one up yet or has just discarded one. The last two * cases can be guessed fairly reliably for code generated * by gcc. The first case is too much trouble to handle in * general because the amount of junk on the stack depends * on the pc (the special handling of "calltrap", etc. in * db_nextframe() works because the `next' pc is special). */ actframe = frame; if (first) { - if (!have_addr) { + if (tf != NULL) { int instr; - instr = db_get_value(callpc, 4, FALSE); + instr = db_get_value(pc, 4, FALSE); if ((instr & 0xffffffff) == 0xe5894855) { /* pushq %rbp; movq %rsp, %rbp */ - actframe = (struct amd64_frame *) - (ddb_regs.tf_rsp - 8); - } else if ((instr & 0x00ffffff) == 0x00e58948) { + actframe = (void *)(get_rsp(tf) - 8); + } else if ((instr & 0xffffff) == 0xe58948) { /* movq %rsp, %rbp */ - actframe = (struct amd64_frame *) - ddb_regs.tf_rsp; - if (ddb_regs.tf_rbp == 0) { - /* Fake caller's frame better. */ + actframe = (void *)get_rsp(tf); + if (tf->tf_rbp == 0) { + /* Fake frame better. */ frame = actframe; } - } else if ((instr & 0x000000ff) == 0x000000c3) { + } else if ((instr & 0xff) == 0xc3) { /* ret */ - actframe = (struct amd64_frame *) - (ddb_regs.tf_rsp - 8); + actframe = (void *)(get_rsp(tf) - 8); } else if (offset == 0) { - /* Probably a symbol in assembler code. */ - actframe = (struct amd64_frame *) - (ddb_regs.tf_rsp - 8); + /* Probably an assembler symbol. */ + actframe = (void *)(get_rsp(tf) - 8); } } else if (strcmp(name, "fork_trampoline") == 0) { /* * Don't try to walk back on a stack for a * process that hasn't actually been run yet. */ - db_print_stack_entry(name, 0, 0, 0, callpc); + db_print_stack_entry(name, 0, 0, 0, pc); break; } first = FALSE; } argp = &actframe->f_arg0; narg = MAXNARG; if (sym != NULL && db_sym_numargs(sym, &narg, argnames)) { argnp = argnames; } else { narg = db_numargs(frame); } - db_print_stack_entry(name, narg, argnp, argp, callpc); + db_print_stack_entry(name, narg, argnp, argp, pc); if (actframe != frame) { /* `frame' belongs to caller. */ - callpc = (db_addr_t) + pc = (db_addr_t) db_get_value((long)&actframe->f_retaddr, 8, FALSE); continue; } - db_nextframe(&frame, &callpc, p); + db_nextframe(&frame, &pc, td); - if (INKERNEL((long) callpc) && !INKERNEL((long) frame)) { - sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); + if (INKERNEL((long)pc) && !INKERNEL((long)frame)) { + sym = db_search_symbol(pc, DB_STGY_ANY, &offset); db_symbol_values(sym, &name, NULL); - db_print_stack_entry(name, 0, 0, 0, callpc); + db_print_stack_entry(name, 0, 0, 0, pc); break; } if (!INKERNEL((long) frame)) { break; } } + + return (0); } void -db_print_backtrace(void) +db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, + char *modif) { - register_t ebp; + struct thread *td; - __asm __volatile("movq %%rbp,%0" : "=r" (ebp)); - db_stack_trace_cmd(ebp, 1, -1, NULL); + td = (have_addr) ? kdb_thr_lookup(addr) : kdb_thread; + if (td == NULL) { + db_printf("Thread %ld not found\n", addr); + return; + } + db_trace_thread(td, count); } -#define DB_DRX_FUNC(reg) \ -int \ -db_ ## reg (vp, valuep, op) \ - struct db_variable *vp; \ - db_expr_t * valuep; \ - int op; \ -{ \ - if (op == DB_VAR_GET) \ - *valuep = r ## reg (); \ - else \ - load_ ## reg (*valuep); \ - return (0); \ -} +void +db_trace_self(void) +{ + struct amd64_frame *frame; + db_addr_t callpc; + register_t rbp; -DB_DRX_FUNC(dr0) -DB_DRX_FUNC(dr1) -DB_DRX_FUNC(dr2) -DB_DRX_FUNC(dr3) -DB_DRX_FUNC(dr4) -DB_DRX_FUNC(dr5) -DB_DRX_FUNC(dr6) -DB_DRX_FUNC(dr7) + __asm __volatile("movq %%rbp,%0" : "=r" (rbp)); + frame = (struct amd64_frame *)rbp; + callpc = (db_addr_t)db_get_value((long)&frame->f_retaddr, 8, FALSE); + frame = frame->f_frame; + db_backtrace(curthread, NULL, frame, callpc, -1); +} + +int +db_trace_thread(struct thread *thr, int count) +{ + struct pcb *ctx; + + ctx = kdb_thr_ctx(thr); + return (db_backtrace(thr, NULL, (struct amd64_frame *)ctx->pcb_rbp, + ctx->pcb_rip, count)); +} int amd64_set_watch(watchnum, watchaddr, size, access, d) int watchnum; unsigned int watchaddr; int size; int access; struct dbreg * d; { int i; unsigned int mask; if (watchnum == -1) { for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2) if ((d->dr[7] & mask) == 0) break; if (i < 4) watchnum = i; else return (-1); } switch (access) { case DBREG_DR7_EXEC: size = 1; /* size must be 1 for an execution breakpoint */ /* fall through */ case DBREG_DR7_WRONLY: case DBREG_DR7_RDWR: break; default : return (-1); } /* * we can watch a 1, 2, or 4 byte sized location */ switch (size) { case 1 : mask = 0x00; break; case 2 : mask = 0x01 << 2; break; case 4 : mask = 0x03 << 2; break; default : return (-1); } mask |= access; /* clear the bits we are about to affect */ d->dr[7] &= ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16))); /* set drN register to the address, N=watchnum */ DBREG_DRX(d,watchnum) = watchaddr; /* enable the watchpoint */ d->dr[7] |= (0x2 << (watchnum*2)) | (mask << (watchnum*4+16)); return (watchnum); } int amd64_clr_watch(watchnum, d) int watchnum; struct dbreg * d; { if (watchnum < 0 || watchnum >= 4) return (-1); d->dr[7] = d->dr[7] & ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16))); DBREG_DRX(d,watchnum) = 0; return (0); } int db_md_set_watchpoint(addr, size) db_expr_t addr; db_expr_t size; { int avail, wsize; int i; struct dbreg d; fill_dbregs(NULL, &d); avail = 0; for(i=0; i<4; i++) { if ((d.dr[7] & (3 << (i*2))) == 0) avail++; } if (avail*4 < size) return (-1); for (i=0; i<4 && (size != 0); i++) { if ((d.dr[7] & (3<<(i*2))) == 0) { if (size > 4) wsize = 4; else wsize = size; if (wsize == 3) wsize++; amd64_set_watch(i, addr, wsize, DBREG_DR7_WRONLY, &d); addr += wsize; size -= wsize; } } set_dbregs(NULL, &d); return(0); } int db_md_clr_watchpoint(addr, size) db_expr_t addr; db_expr_t size; { int i; struct dbreg d; fill_dbregs(NULL, &d); for(i=0; i<4; i++) { if (d.dr[7] & (3 << (i*2))) { if ((DBREG_DRX((&d), i) >= addr) && (DBREG_DRX((&d), i) < addr+size)) amd64_clr_watch(i, &d); } } set_dbregs(NULL, &d); return(0); } static char * watchtype_str(type) int type; { switch (type) { case DBREG_DR7_EXEC : return "execute"; break; case DBREG_DR7_RDWR : return "read/write"; break; case DBREG_DR7_WRONLY : return "write"; break; default : return "invalid"; break; } } void db_md_list_watchpoints() { int i; struct dbreg d; fill_dbregs(NULL, &d); db_printf("\nhardware watchpoints:\n"); db_printf(" watch status type len address\n"); db_printf(" ----- -------- ---------- --- ----------\n"); for (i=0; i<4; i++) { if (d.dr[7] & (0x03 << (i*2))) { unsigned type, len; type = (d.dr[7] >> (16+(i*4))) & 3; len = (d.dr[7] >> (16+(i*4)+2)) & 3; db_printf(" %-5d %-8s %10s %3d 0x%016lx\n", i, "enabled", watchtype_str(type), len + 1, DBREG_DRX((&d), i)); } else { db_printf(" %-5d disabled\n", i); } } db_printf("\ndebug register values:\n"); for (i=0; i<8; i++) { db_printf(" dr%d 0x%016lx\n", i, DBREG_DRX((&d), i)); } db_printf("\n"); } Index: head/sys/amd64/include/db_machdep.h =================================================================== --- head/sys/amd64/include/db_machdep.h (revision 131951) +++ head/sys/amd64/include/db_machdep.h (revision 131952) @@ -1,93 +1,86 @@ /* * Mach Operating System * Copyright (c) 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. * * $FreeBSD$ */ #ifndef _MACHINE_DB_MACHDEP_H_ #define _MACHINE_DB_MACHDEP_H_ #include -#include #include -#define amd64_saved_state trapframe - typedef vm_offset_t db_addr_t; /* address - unsigned */ typedef long db_expr_t; /* expression - signed */ -typedef struct amd64_saved_state db_regs_t; -extern db_regs_t ddb_regs; /* register state */ -#define DDB_REGS (&ddb_regs) +#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_rip) -#define PC_REGS(regs) ((db_addr_t)(regs)->tf_rip) - #define BKPT_INST 0xcc /* breakpoint instruction */ #define BKPT_SIZE (1) /* size of breakpoint inst */ #define BKPT_SET(inst) (BKPT_INST) -#define BKPT_SKIP ddb_regs.tf_rip += 1 +#define BKPT_SKIP kdb_frame->tf_rip += 1 -#define FIXUP_PC_AFTER_BREAK ddb_regs.tf_rip -= 1; +#define FIXUP_PC_AFTER_BREAK kdb_frame->tf_rip -= 1; -#define db_clear_single_step(regs) ((regs)->tf_rflags &= ~PSL_T) -#define db_set_single_step(regs) ((regs)->tf_rflags |= PSL_T) +#define db_clear_single_step kdb_cpu_clear_singlestep +#define db_set_single_step kdb_cpu_set_singlestep #define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT) /* * Watchpoints are not supported. The debug exception type is in %dr6 * and not yet in the args to this macro. */ #define IS_WATCHPOINT_TRAP(type, code) 0 #define I_CALL 0xe8 #define I_CALLI 0xff #define I_RET 0xc3 #define I_IRET 0xcf #define inst_trap_return(ins) (((ins)&0xff) == I_IRET) #define inst_return(ins) (((ins)&0xff) == I_RET) #define inst_call(ins) (((ins)&0xff) == I_CALL || \ (((ins)&0xff) == I_CALLI && \ ((ins)&0x3800) == 0x1000)) #define inst_load(ins) 0 #define inst_store(ins) 0 /* * There no interesting addresses below _kstack = 0xefbfe000. There * are small absolute values for GUPROF, but we don't want to see them. * Treat "negative" addresses below _kstack as non-small to allow for * future reductions of _kstack and to avoid sign extension problems. * * There is one interesting symbol above -db_maxoff = 0xffff0000, * namely _APTD = 0xfffff000. Accepting this would mess up the * printing of small negative offsets. The next largest symbol is * _APTmap = 0xffc00000. Accepting this is OK (unless db_maxoff is * set to >= 0x400000 - (max stack offset)). */ #define DB_SMALL_VALUE_MAX 0x7fffffff #define DB_SMALL_VALUE_MIN (-0x400001) #endif /* !_MACHINE_DB_MACHDEP_H_ */ Index: head/sys/conf/files =================================================================== --- head/sys/conf/files (revision 131951) +++ head/sys/conf/files (revision 131952) @@ -1,1715 +1,1713 @@ # $FreeBSD$ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and # dependency lines other than the first are silently ignored. # acpi_quirks.h optional acpi \ dependency "$S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \ compile-with "${AWK} -f $S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \ no-obj no-implicit-rule before-depend \ clean "acpi_quirks.h" aicasm optional ahc \ dependency "$S/dev/aic7xxx/aicasm/*.[chyl]" \ compile-with "CC=${CC} ${MAKE} -f $S/dev/aic7xxx/aicasm/Makefile MAKESRCPATH=$S/dev/aic7xxx/aicasm" \ no-obj no-implicit-rule \ clean "aicasm* y.tab.h" aicasm optional ahd \ dependency "$S/dev/aic7xxx/aicasm/*.[chyl]" \ compile-with "CC=${CC} ${MAKE} -f $S/dev/aic7xxx/aicasm/Makefile MAKESRCPATH=$S/dev/aic7xxx/aicasm" \ no-obj no-implicit-rule \ clean "aicasm* y.tab.h" aic7xxx_{seq.h,reg.h,reg_print.c} optional ahc \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic7xxx_seq.h -r aic7xxx_reg.h -p aic7xxx_reg_print.c -i $S/dev/aic7xxx/aic7xxx_osm.h $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule before-depend \ clean "aic7xxx_seq.h aic7xxx_reg.h aic7xxx_reg_print.c" \ dependency "$S/dev/aic7xxx/aic7xxx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic7xxx_reg_print.o optional ahc ahc_reg_pretty_print \ compile-with "${NORMAL_C}" \ no-implicit-rule local aic79xx_{seq.h,reg.h,reg_print.c} optional ahd pci \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic79xx_seq.h -r aic79xx_reg.h -p aic79xx_reg_print.c -i $S/dev/aic7xxx/aic79xx_osm.h $S/dev/aic7xxx/aic79xx.seq" \ no-obj no-implicit-rule before-depend \ clean "aic79xx_seq.h aic79xx_reg.h aic79xx_reg_print.c" \ dependency "$S/dev/aic7xxx/aic79xx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic79xx_reg_print.o optional ahd pci ahd_reg_pretty_print \ compile-with "${NORMAL_C}" \ no-implicit-rule local emu10k1-alsa%diked.h optional pcm pci \ dependency "$S/tools/emu10k1-mkalsa.sh $S/gnu/dev/sound/pci/emu10k1-alsa.h" \ compile-with "CC=${CC} AWK=${AWK} sh $S/tools/emu10k1-mkalsa.sh $S/gnu/dev/sound/pci/emu10k1-alsa.h emu10k1-alsa%diked.h" \ no-obj no-implicit-rule before-depend \ clean "emu10k1-alsa%diked.h" miidevs.h optional miibus \ dependency "$S/tools/miidevs2h.awk $S/dev/mii/miidevs" \ compile-with "${AWK} -f $S/tools/miidevs2h.awk $S/dev/mii/miidevs" \ no-obj no-implicit-rule before-depend \ clean "miidevs.h" pccarddevs.h standard \ dependency "$S/tools/pccarddevs2h.awk $S/dev/pccard/pccarddevs" \ compile-with "${AWK} -f $S/tools/pccarddevs2h.awk $S/dev/pccard/pccarddevs" \ no-obj no-implicit-rule before-depend \ clean "pccarddevs.h" usbdevs.h optional usb \ dependency "$S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \ compile-with "${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \ no-obj no-implicit-rule before-depend \ clean "usbdevs.h" kern/device_if.m standard kern/bus_if.m standard kern/clock_if.m optional genclock kern/linker_if.m standard cam/cam.c optional scbus cam/cam_periph.c optional scbus cam/cam_queue.c optional scbus cam/cam_sim.c optional scbus cam/cam_xpt.c optional scbus cam/scsi/scsi_all.c optional scbus cam/scsi/scsi_cd.c optional cd cam/scsi/scsi_ch.c optional ch cam/scsi/scsi_da.c optional da cam/scsi/scsi_low.c optional ct cam/scsi/scsi_low.c optional ncv cam/scsi/scsi_low.c optional nsp cam/scsi/scsi_low.c optional stg cam/scsi/scsi_low_pisa.c optional ct cam/scsi/scsi_low_pisa.c optional ncv cam/scsi/scsi_low_pisa.c optional nsp cam/scsi/scsi_low_pisa.c optional stg cam/scsi/scsi_pass.c optional pass cam/scsi/scsi_pt.c optional pt cam/scsi/scsi_sa.c optional sa cam/scsi/scsi_ses.c optional ses cam/scsi/scsi_targ_bh.c optional targbh cam/scsi/scsi_target.c optional targ coda/coda_fbsd.c count vcoda coda/coda_namecache.c optional vcoda coda/coda_psdev.c optional vcoda coda/coda_subr.c optional vcoda coda/coda_venus.c optional vcoda coda/coda_vfsops.c optional vcoda coda/coda_vnops.c optional vcoda compat/linprocfs/linprocfs.c optional linprocfs contrib/altq/altq/altq_cbq.c optional altq contrib/altq/altq/altq_cdnr.c optional altq contrib/altq/altq/altq_hfsc.c optional altq contrib/altq/altq/altq_priq.c optional altq contrib/altq/altq/altq_red.c optional altq contrib/altq/altq/altq_rio.c optional altq contrib/altq/altq/altq_rmclass.c optional altq contrib/altq/altq/altq_subr.c optional altq contrib/dev/acpica/dbcmds.c optional acpi acpi_debug contrib/dev/acpica/dbdisply.c optional acpi acpi_debug contrib/dev/acpica/dbexec.c optional acpi acpi_debug contrib/dev/acpica/dbfileio.c optional acpi acpi_debug contrib/dev/acpica/dbhistry.c optional acpi acpi_debug contrib/dev/acpica/dbinput.c optional acpi acpi_debug contrib/dev/acpica/dbstats.c optional acpi acpi_debug contrib/dev/acpica/dbutils.c optional acpi acpi_debug contrib/dev/acpica/dbxface.c optional acpi acpi_debug contrib/dev/acpica/dmbuffer.c optional acpi acpi_debug contrib/dev/acpica/dmnames.c optional acpi acpi_debug contrib/dev/acpica/dmopcode.c optional acpi acpi_debug contrib/dev/acpica/dmobject.c optional acpi acpi_debug contrib/dev/acpica/dmresrc.c optional acpi acpi_debug contrib/dev/acpica/dmresrcl.c optional acpi acpi_debug contrib/dev/acpica/dmresrcs.c optional acpi acpi_debug contrib/dev/acpica/dmutils.c optional acpi acpi_debug contrib/dev/acpica/dmwalk.c optional acpi acpi_debug contrib/dev/acpica/dsfield.c optional acpi contrib/dev/acpica/dsinit.c optional acpi contrib/dev/acpica/dsmethod.c optional acpi contrib/dev/acpica/dsmthdat.c optional acpi contrib/dev/acpica/dsobject.c optional acpi contrib/dev/acpica/dsopcode.c optional acpi contrib/dev/acpica/dsutils.c optional acpi contrib/dev/acpica/dswexec.c optional acpi contrib/dev/acpica/dswload.c optional acpi contrib/dev/acpica/dswscope.c optional acpi contrib/dev/acpica/dswstate.c optional acpi contrib/dev/acpica/evevent.c optional acpi contrib/dev/acpica/evgpe.c optional acpi contrib/dev/acpica/evgpeblk.c optional acpi contrib/dev/acpica/evmisc.c optional acpi contrib/dev/acpica/evregion.c optional acpi contrib/dev/acpica/evrgnini.c optional acpi contrib/dev/acpica/evsci.c optional acpi contrib/dev/acpica/evxface.c optional acpi contrib/dev/acpica/evxfevnt.c optional acpi contrib/dev/acpica/evxfregn.c optional acpi contrib/dev/acpica/exconfig.c optional acpi contrib/dev/acpica/exconvrt.c optional acpi contrib/dev/acpica/excreate.c optional acpi contrib/dev/acpica/exdump.c optional acpi contrib/dev/acpica/exfield.c optional acpi contrib/dev/acpica/exfldio.c optional acpi contrib/dev/acpica/exmisc.c optional acpi contrib/dev/acpica/exmutex.c optional acpi contrib/dev/acpica/exnames.c optional acpi contrib/dev/acpica/exoparg1.c optional acpi contrib/dev/acpica/exoparg2.c optional acpi contrib/dev/acpica/exoparg3.c optional acpi contrib/dev/acpica/exoparg6.c optional acpi contrib/dev/acpica/exprep.c optional acpi contrib/dev/acpica/exregion.c optional acpi contrib/dev/acpica/exresnte.c optional acpi contrib/dev/acpica/exresolv.c optional acpi contrib/dev/acpica/exresop.c optional acpi contrib/dev/acpica/exstore.c optional acpi contrib/dev/acpica/exstoren.c optional acpi contrib/dev/acpica/exstorob.c optional acpi contrib/dev/acpica/exsystem.c optional acpi contrib/dev/acpica/exutils.c optional acpi contrib/dev/acpica/hwacpi.c optional acpi contrib/dev/acpica/hwgpe.c optional acpi contrib/dev/acpica/hwregs.c optional acpi contrib/dev/acpica/hwsleep.c optional acpi contrib/dev/acpica/hwtimer.c optional acpi contrib/dev/acpica/nsaccess.c optional acpi contrib/dev/acpica/nsalloc.c optional acpi contrib/dev/acpica/nsdump.c optional acpi contrib/dev/acpica/nseval.c optional acpi contrib/dev/acpica/nsinit.c optional acpi contrib/dev/acpica/nsload.c optional acpi contrib/dev/acpica/nsnames.c optional acpi contrib/dev/acpica/nsobject.c optional acpi contrib/dev/acpica/nsparse.c optional acpi contrib/dev/acpica/nssearch.c optional acpi contrib/dev/acpica/nsutils.c optional acpi contrib/dev/acpica/nswalk.c optional acpi contrib/dev/acpica/nsxfeval.c optional acpi contrib/dev/acpica/nsxfname.c optional acpi contrib/dev/acpica/nsxfobj.c optional acpi contrib/dev/acpica/psargs.c optional acpi contrib/dev/acpica/psopcode.c optional acpi contrib/dev/acpica/psparse.c optional acpi contrib/dev/acpica/psscope.c optional acpi contrib/dev/acpica/pstree.c optional acpi contrib/dev/acpica/psutils.c optional acpi contrib/dev/acpica/pswalk.c optional acpi contrib/dev/acpica/psxface.c optional acpi contrib/dev/acpica/rsaddr.c optional acpi contrib/dev/acpica/rscalc.c optional acpi contrib/dev/acpica/rscreate.c optional acpi contrib/dev/acpica/rsdump.c optional acpi contrib/dev/acpica/rsio.c optional acpi contrib/dev/acpica/rsirq.c optional acpi contrib/dev/acpica/rslist.c optional acpi contrib/dev/acpica/rsmemory.c optional acpi contrib/dev/acpica/rsmisc.c optional acpi contrib/dev/acpica/rsutils.c optional acpi contrib/dev/acpica/rsxface.c optional acpi contrib/dev/acpica/tbconvrt.c optional acpi contrib/dev/acpica/tbget.c optional acpi contrib/dev/acpica/tbgetall.c optional acpi contrib/dev/acpica/tbinstal.c optional acpi contrib/dev/acpica/tbrsdt.c optional acpi contrib/dev/acpica/tbutils.c optional acpi contrib/dev/acpica/tbxface.c optional acpi contrib/dev/acpica/tbxfroot.c optional acpi contrib/dev/acpica/utalloc.c optional acpi contrib/dev/acpica/utclib.c optional acpi contrib/dev/acpica/utcopy.c optional acpi contrib/dev/acpica/utdebug.c optional acpi contrib/dev/acpica/utdelete.c optional acpi contrib/dev/acpica/uteval.c optional acpi contrib/dev/acpica/utglobal.c optional acpi contrib/dev/acpica/utinit.c optional acpi contrib/dev/acpica/utmath.c optional acpi contrib/dev/acpica/utmisc.c optional acpi contrib/dev/acpica/utobject.c optional acpi contrib/dev/acpica/utxface.c optional acpi contrib/dev/ath/freebsd/ah_osdep.c optional ath_hal contrib/ipfilter/netinet/fil.c optional ipfilter inet contrib/ipfilter/netinet/ip_auth.c optional ipfilter inet contrib/ipfilter/netinet/ip_fil.c optional ipfilter inet contrib/ipfilter/netinet/ip_frag.c optional ipfilter inet contrib/ipfilter/netinet/ip_log.c optional ipfilter inet contrib/ipfilter/netinet/ip_nat.c optional ipfilter inet contrib/ipfilter/netinet/ip_proxy.c optional ipfilter inet contrib/ipfilter/netinet/ip_state.c optional ipfilter inet contrib/ipfilter/netinet/mlfk_ipl.c optional ipfilter inet contrib/pf/net/if_pflog.c optional pflog contrib/pf/net/if_pfsync.c optional pfsync contrib/pf/net/pf.c optional pf contrib/pf/net/pf_if.c optional pf contrib/pf/net/pf_subr.c optional pf contrib/pf/net/pf_ioctl.c optional pf contrib/pf/net/pf_norm.c optional pf contrib/pf/net/pf_table.c optional pf contrib/pf/net/pf_osfp.c optional pf contrib/pf/netinet/in4_cksum.c optional pf inet crypto/blowfish/bf_ecb.c optional ipsec ipsec_esp crypto/blowfish/bf_skey.c optional ipsec ipsec_esp crypto/cast128/cast128.c optional ipsec ipsec_esp crypto/des/des_ecb.c optional ipsec ipsec_esp crypto/des/des_setkey.c optional ipsec ipsec_esp crypto/rijndael/rijndael-alg-fst.c optional ipsec crypto/rijndael/rijndael-api.c optional ipsec opencrypto/rmd160.c optional ipsec crypto/sha1.c optional ipsec crypto/sha2/sha2.c optional ipsec -ddb/db_access.c optional ddb -ddb/db_break.c optional ddb -ddb/db_command.c optional ddb -ddb/db_elf.c optional ddb -ddb/db_examine.c optional ddb -ddb/db_expr.c optional ddb -ddb/db_input.c optional ddb -ddb/db_kld.c optional ddb -ddb/db_lex.c optional ddb -ddb/db_output.c optional ddb -ddb/db_print.c optional ddb -ddb/db_ps.c optional ddb -ddb/db_run.c optional ddb -ddb/db_sym.c optional ddb -ddb/db_sysctl.c optional ddb -ddb/db_trap.c optional ddb -ddb/db_variables.c optional ddb -ddb/db_watch.c optional ddb -ddb/db_write_cmd.c optional ddb +ddb/db_access.c optional ddb +ddb/db_break.c optional ddb +ddb/db_command.c optional ddb +ddb/db_examine.c optional ddb +ddb/db_expr.c optional ddb +ddb/db_input.c optional ddb +ddb/db_lex.c optional ddb +ddb/db_main.c optional ddb +ddb/db_output.c optional ddb +ddb/db_print.c optional ddb +ddb/db_ps.c optional ddb +ddb/db_run.c optional ddb +ddb/db_sym.c optional ddb +ddb/db_thread.c optional ddb +ddb/db_variables.c optional ddb +ddb/db_watch.c optional ddb +ddb/db_write_cmd.c optional ddb dev/aac/aac.c optional aac dev/aac/aac_debug.c optional aac dev/aac/aac_disk.c optional aac dev/aac/aac_pci.c optional aac pci dev/aac/aac_cam.c optional aacp aac dev/aac/aac_linux.c optional aac compat_linux dev/acpica/acpi.c optional acpi dev/acpica/acpi_acad.c optional acpi dev/acpica/acpi_battery.c optional acpi dev/acpica/acpi_button.c optional acpi dev/acpica/acpi_cmbat.c optional acpi dev/acpica/acpi_cpu.c optional acpi dev/acpica/acpi_ec.c optional acpi dev/acpica/acpi_isab.c optional acpi isa dev/acpica/acpi_lid.c optional acpi dev/acpica/acpi_package.c optional acpi dev/acpica/acpi_pci.c optional acpi pci dev/acpica/acpi_pci_link.c optional acpi pci dev/acpica/acpi_pcib.c optional acpi pci dev/acpica/acpi_pcib_acpi.c optional acpi pci dev/acpica/acpi_pcib_pci.c optional acpi pci dev/acpica/acpi_powerres.c optional acpi dev/acpica/acpi_quirk.c optional acpi dev/acpica/acpi_resource.c optional acpi dev/acpica/acpi_thermal.c optional acpi dev/acpica/acpi_timer.c optional acpi dev/acpica/Osd/OsdDebug.c optional acpi dev/acpica/Osd/OsdHardware.c optional acpi dev/acpica/Osd/OsdInterrupt.c optional acpi dev/acpica/Osd/OsdMemory.c optional acpi dev/acpica/Osd/OsdSchedule.c optional acpi dev/acpica/Osd/OsdStream.c optional acpi dev/acpica/Osd/OsdSynch.c optional acpi dev/acpica/Osd/OsdTable.c optional acpi dev/acpica/acpi_video.c optional acpi_video acpi dev/adlink/adlink.c optional adlink dev/advansys/adv_eisa.c optional adv eisa dev/advansys/adv_pci.c optional adv pci dev/advansys/advansys.c optional adv dev/advansys/advlib.c optional adv dev/advansys/advmcode.c optional adv dev/advansys/adw_pci.c optional adw pci dev/advansys/adwcam.c optional adw dev/advansys/adwlib.c optional adw dev/advansys/adwmcode.c optional adw dev/aha/aha.c optional aha dev/aha/aha_isa.c optional aha isa dev/aha/aha_mca.c optional aha mca dev/ahb/ahb.c optional ahb eisa dev/aic/aic.c optional aic dev/aic/aic_pccard.c optional aic card dev/aic/aic_pccard.c optional aic pccard dev/aic7xxx/aic7770.c optional ahc eisa dev/aic7xxx/ahc_eisa.c optional ahc eisa #dev/aic7xxx/ahc_isa.c optional ahc isa dev/aic7xxx/ahc_pci.c optional ahc pci dev/aic7xxx/aic7xxx.c optional ahc dev/aic7xxx/aic7xxx_93cx6.c optional ahc dev/aic7xxx/aic7xxx_osm.c optional ahc dev/aic7xxx/aic7xxx_pci.c optional ahc pci dev/aic7xxx/ahd_pci.c optional ahd pci dev/aic7xxx/aic79xx.c optional ahd pci dev/aic7xxx/aic79xx_osm.c optional ahd pci dev/aic7xxx/aic79xx_pci.c optional ahd pci dev/amd/amd.c optional amd dev/amr/amr_cam.c optional amr dev/amr/amr.c optional amr dev/amr/amr_disk.c optional amr dev/amr/amr_pci.c optional amr pci dev/an/if_an.c optional an dev/an/if_an_isa.c optional an isa dev/an/if_an_pccard.c optional an card dev/an/if_an_pccard.c optional an pccard dev/an/if_an_pci.c optional an pci dev/asr/asr.c optional asr pci dev/ata/ata-all.c optional ata dev/ata/ata-queue.c optional ata dev/ata/ata-lowlevel.c optional ata dev/ata/ata-isa.c optional ata isa dev/ata/ata-cbus.c optional ata pc98 dev/ata/ata-card.c optional ata card dev/ata/ata-card.c optional ata pccard dev/ata/ata-pci.c optional ata pci dev/ata/ata-chipset.c optional ata pci dev/ata/ata-dma.c optional ata pci dev/ata/ata-disk.c optional atadisk dev/ata/ata-raid.c optional ataraid dev/ata/atapi-cd.c optional atapicd dev/ata/atapi-fd.c optional atapifd dev/ata/atapi-tape.c optional atapist dev/ata/atapi-cam.c optional atapicam dev/ath/if_ath.c optional ath dev/ath/if_ath_pci.c optional ath pci dev/ath/if_ath_pci.c optional ath card dev/awi/am79c930.c optional awi dev/awi/awi.c optional awi dev/awi/if_awi_pccard.c optional awi card dev/awi/if_awi_pccard.c optional awi pccard dev/bfe/if_bfe.c optional bfe dev/bge/if_bge.c optional bge dev/bktr/bktr_audio.c optional bktr pci dev/bktr/bktr_card.c optional bktr pci dev/bktr/bktr_core.c optional bktr pci dev/bktr/bktr_i2c.c optional bktr pci smbus dev/bktr/bktr_os.c optional bktr pci dev/bktr/bktr_tuner.c optional bktr pci dev/bktr/msp34xx.c optional bktr pci dev/buslogic/bt.c optional bt dev/buslogic/bt_eisa.c optional bt eisa dev/buslogic/bt_isa.c optional bt isa dev/buslogic/bt_mca.c optional bt mca dev/buslogic/bt_pci.c optional bt pci dev/cardbus/cardbus.c optional cardbus dev/cardbus/cardbus_cis.c optional cardbus dev/ciss/ciss.c optional ciss dev/cm/smc90cx6.c optional cm dev/cnw/if_cnw.c optional cnw card #dev/cnw/if_cnw.c optional cnw pccard dev/cs/if_cs.c optional cs dev/cs/if_cs_isa.c optional cs isa dev/cs/if_cs_pccard.c optional cs card dev/cs/if_cs_pccard.c optional cs pccard dev/cy/cy.c optional cy dev/cy/cy_isa.c optional cy isa dev/cy/cy_pci.c optional cy pci dev/dcons/dcons.c optional dcons dev/dcons/dcons_crom.c optional dcons_crom dev/digi/digi.c optional digi dev/digi/digi_isa.c optional digi isa dev/digi/digi_pci.c optional digi pci dev/digi/CX.c optional digi_CX dev/digi/CX_PCI.c optional digi_CX_PCI dev/digi/EPCX.c optional digi_EPCX dev/digi/EPCX_PCI.c optional digi_EPCX_PCI dev/digi/Xe.c optional digi_Xe dev/digi/Xem.c optional digi_Xem dev/digi/Xr.c optional digi_Xr #dev/dpt/dpt_control.c optional dpt dev/dpt/dpt_eisa.c optional dpt eisa dev/dpt/dpt_pci.c optional dpt pci dev/dpt/dpt_scsi.c optional dpt dev/drm/mga_dma.c optional mgadrm dev/drm/mga_drv.c optional mgadrm dev/drm/mga_irq.c optional mgadrm dev/drm/mga_state.c optional mgadrm \ compile-with "${NORMAL_C} -finline-limit=13500" dev/drm/mga_warp.c optional mgadrm dev/drm/r128_cce.c optional r128drm dev/drm/r128_drv.c optional r128drm dev/drm/r128_irq.c optional r128drm dev/drm/r128_state.c optional r128drm \ compile-with "${NORMAL_C} -finline-limit=13500" dev/drm/radeon_cp.c optional radeondrm dev/drm/radeon_drv.c optional radeondrm dev/drm/radeon_irq.c optional radeondrm dev/drm/radeon_mem.c optional radeondrm dev/drm/radeon_state.c optional radeondrm dev/drm/sis_drv.c optional sisdrm dev/drm/sis_ds.c optional sisdrm dev/drm/sis_mm.c optional sisdrm dev/drm/tdfx_drv.c optional tdfxdrm dev/ed/if_ed.c optional ed dev/ed/if_ed_pccard.c optional ed card dev/ed/if_ed_pccard.c optional ed pccard dev/ed/if_ed_pci.c optional ed pci dev/eisa/eisa_if.m standard dev/eisa/eisaconf.c optional eisa dev/em/if_em.c optional em dev/em/if_em_hw.c optional em dev/en/midway.c optional en dev/en/if_en_pci.c optional en pci dev/ep/if_ep.c optional ep dev/ep/if_ep_eisa.c optional ep eisa dev/ep/if_ep_isa.c optional ep isa dev/ep/if_ep_mca.c optional ep mca dev/ep/if_ep_pccard.c optional ep card dev/ep/if_ep_pccard.c optional ep pccard dev/esp/ncr53c9x.c optional esp dev/ex/if_ex.c optional ex dev/ex/if_ex_isa.c optional ex isa dev/ex/if_ex_pccard.c optional ex card #dev/ex/if_ex_pccard.c optional ex pccard dev/exca/exca.c optional cbb dev/fatm/if_fatm.c optional fatm pci dev/fe/if_fe.c optional fe dev/fe/if_fe_pccard.c optional fe card dev/fe/if_fe_pccard.c optional fe pccard dev/firewire/firewire.c optional firewire dev/firewire/fwcrom.c optional firewire dev/firewire/fwdev.c optional firewire dev/firewire/fwdma.c optional firewire dev/firewire/fwmem.c optional firewire dev/firewire/fwohci.c optional firewire dev/firewire/fwohci_pci.c optional firewire pci dev/firewire/if_fwe.c optional fwe dev/firewire/if_fwip.c optional fwip dev/firewire/sbp.c optional sbp dev/firewire/sbp_targ.c optional sbp_targ dev/fxp/if_fxp.c optional fxp dev/gem/if_gem.c optional gem dev/gem/if_gem_pci.c optional gem pci dev/gx/if_gx.c optional gx dev/harp/if_harp.c optional harp pci dev/hatm/if_hatm.c optional hatm pci dev/hatm/if_hatm_intr.c optional hatm pci dev/hatm/if_hatm_ioctl.c optional hatm pci dev/hatm/if_hatm_rx.c optional hatm pci dev/hatm/if_hatm_tx.c optional hatm pci dev/hfa/fore_buffer.c optional hfa dev/hfa/fore_command.c optional hfa dev/hfa/fore_globals.c optional hfa dev/hfa/fore_if.c optional hfa dev/hfa/fore_init.c optional hfa dev/hfa/fore_intr.c optional hfa dev/hfa/fore_output.c optional hfa dev/hfa/fore_receive.c optional hfa dev/hfa/fore_stats.c optional hfa dev/hfa/fore_timer.c optional hfa dev/hfa/fore_transmit.c optional hfa dev/hfa/fore_vcm.c optional hfa dev/hfa/hfa_freebsd.c optional hfa #dev/hfa/hfa_eisa.c optional hfa eisa dev/hfa/hfa_pci.c optional hfa pci #dev/hfa/hfa_sbus.c optional hfa sbus dev/hifn/hifn7751.c optional hifn dev/hme/if_hme.c optional hme dev/hme/if_hme_pci.c optional hme pci dev/hme/if_hme_sbus.c optional hme sbus dev/ichsmb/ichsmb.c optional ichsmb dev/ichsmb/ichsmb_pci.c optional ichsmb pci dev/ida/ida.c optional ida dev/ida/ida_disk.c optional ida dev/ida/ida_eisa.c optional ida eisa dev/ida/ida_pci.c optional ida pci dev/ie/if_ie.c optional ie isa nowerror dev/ie/if_ie_isa.c optional ie isa dev/iicbus/iicbb_if.m optional iicbb dev/iicbus/iicbus_if.m optional iicbus dev/iicbus/if_ic.c optional ic dev/iicbus/iic.c optional iic dev/iicbus/iicbb.c optional iicbb dev/iicbus/iicbus.c optional iicbus dev/iicbus/iiconf.c optional iicbus dev/iicbus/iicsmb.c optional iicsmb \ dependency "iicbus_if.h" dev/iir/iir.c optional iir dev/iir/iir_ctrl.c optional iir dev/iir/iir_pci.c optional iir pci dev/ips/ips.c optional ips dev/ips/ips_pci.c optional ips pci dev/ips/ips_disk.c optional ips dev/ips/ips_commands.c optional ips dev/ips/ips_ioctl.c optional ips dev/isp/isp.c optional isp dev/isp/isp_freebsd.c optional isp dev/isp/isp_target.c optional isp dev/isp/isp_pci.c optional isp pci dev/isp/isp_sbus.c optional isp sbus dev/ispfw/ispfw.c optional ispfw dev/ixgb/ixgb_hw.c optional ixgb dev/ixgb/ixgb_ee.c optional ixgb dev/ixgb/if_ixgb.c optional ixgb dev/joy/joy.c optional joy dev/joy/joy_isa.c optional joy isa dev/joy/joy_pccard.c optional joy pccard dev/led/led.c standard dev/lge/if_lge.c optional lge dev/lnc/if_lnc.c optional lnc dev/lnc/if_lnc_pci.c optional lnc pci dev/ncv/ncr53c500.c optional ncv dev/ncv/ncr53c500_pccard.c optional ncv card dev/ncv/ncr53c500_pccard.c optional ncv pccard dev/nsp/nsp.c optional nsp dev/nsp/nsp_pccard.c optional nsp card dev/nsp/nsp_pccard.c optional nsp pccard dev/mca/mca_bus.c optional mca dev/mcd/mcd.c optional mcd isa nowerror dev/mcd/mcd_isa.c optional mcd isa nowerror dev/md/md.c optional md dev/mii/amphy.c optional miibus dev/mii/bmtphy.c optional miibus dev/mii/brgphy.c optional miibus dev/mii/dcphy.c optional miibus pci dev/mii/e1000phy.c optional miibus dev/mii/exphy.c optional miibus dev/mii/inphy.c optional miibus dev/mii/mii.c optional miibus dev/mii/mii_physubr.c optional miibus dev/mii/mlphy.c optional miibus dev/mii/nsphy.c optional miibus dev/mii/nsgphy.c optional miibus dev/mii/pnphy.c optional miibus dev/mii/pnaphy.c optional miibus dev/mii/rgephy.c optional miibus dev/mii/rlphy.c optional miibus dev/mii/ruephy.c optional miibus dev/mii/tdkphy.c optional miibus dev/mii/tlphy.c optional miibus dev/mii/ukphy.c optional miibus dev/mii/ukphy_subr.c optional miibus dev/mii/xmphy.c optional miibus dev/mii/lxtphy.c optional miibus dev/mii/qsphy.c optional miibus dev/mii/acphy.c optional miibus dev/mii/miibus_if.m optional miibus dev/mk48txx/mk48txx.c optional mk48txx dev/mlx/mlx.c optional mlx dev/mlx/mlx_disk.c optional mlx dev/mlx/mlx_pci.c optional mlx pci dev/mly/mly.c optional mly dev/mpt/mpt.c optional mpt dev/mpt/mpt_debug.c optional mpt dev/mpt/mpt_freebsd.c optional mpt dev/mpt/mpt_pci.c optional mpt pci dev/my/if_my.c optional my dev/musycc/musycc.c optional musycc dev/nge/if_nge.c optional nge dev/null/null.c standard dev/nmdm/nmdm.c optional nmdm dev/patm/if_patm.c optional patm pci dev/patm/if_patm_intr.c optional patm pci dev/patm/if_patm_ioctl.c optional patm pci dev/patm/if_patm_rx.c optional patm pci dev/patm/if_patm_tx.c optional patm pci dev/patm/if_patm_attach.c optional patm pci dev/patm/if_patm_rtables.c optional patm pci dev/pccard/card_if.m standard dev/pccard/pccard.c optional pccard dev/pccard/pccard_cis.c optional pccard dev/pccard/pccard_cis_quirks.c optional pccard dev/pccard/power_if.m standard dev/pccbb/pccbb.c optional cbb dev/pci/eisa_pci.c optional pci eisa dev/pci/fixup_pci.c optional pci dev/pci/ignore_pci.c optional pci dev/pci/isa_pci.c optional pci isa dev/pci/pci.c optional pci dev/pci/pci_if.m standard dev/pci/pci_pci.c optional pci dev/pci/pci_user.c optional pci dev/pci/pcib_if.m standard dev/pcic/i82365.c optional pcic pccard dev/pcic/i82365_isa.c optional pcic pccard isa dev/pdq/if_fea.c optional fea eisa dev/pdq/if_fpa.c optional fpa pci dev/pdq/pdq.c optional fea eisa nowerror dev/pdq/pdq.c optional fpa pci nowerror dev/pdq/pdq_ifsubr.c optional fea eisa nowerror dev/pdq/pdq_ifsubr.c optional fpa pci nowerror dev/ppbus/ppbus_if.m optional ppbus dev/ppbus/if_plip.c optional plip dev/ppbus/immio.c optional vpo dev/ppbus/lpbb.c optional lpbb dev/ppbus/lpt.c optional lpt dev/ppbus/pcfclock.c optional pcfclock dev/ppbus/ppb_1284.c optional ppbus dev/ppbus/ppb_base.c optional ppbus dev/ppbus/ppb_msq.c optional ppbus dev/ppbus/ppbconf.c optional ppbus dev/ppbus/ppi.c optional ppi dev/ppbus/pps.c optional pps dev/ppbus/vpo.c optional vpo dev/ppbus/vpoio.c optional vpo dev/pst/pst-pci.c optional pst pci dev/pst/pst-iop.c optional pst dev/pst/pst-raid.c optional pst dev/puc/puc.c optional puc dev/puc/puc_ebus.c optional puc ebus dev/puc/puc_pci.c optional puc pci dev/puc/puc_pccard.c optional puc pccard dev/puc/puc_sbus.c optional puc sbus dev/puc/pucdata.c optional puc pci dev/random/harvest.c standard dev/random/randomdev.c optional random dev/random/randomdev_soft.c optional random dev/random/probe.c optional random dev/random/yarrow.c optional random dev/random/hash.c optional random crypto/rijndael/rijndael-alg-fst.c optional random crypto/rijndael/rijndael-api-fst.c optional random crypto/sha2/sha2.c optional random dev/ray/if_ray.c optional ray card dev/ray/if_ray.c optional ray pccard dev/rc/rc.c optional rc dev/re/if_re.c optional re dev/rndtest/rndtest.c optional rndtest dev/rp/rp.c optional rp dev/rp/rp_isa.c optional rp isa dev/rp/rp_pci.c optional rp pci dev/sab/sab.c optional sab ebus dev/safe/safe.c optional safe dev/sbsh/if_sbsh.c optional sbsh dev/scd/scd.c optional scd isa dev/scd/scd_isa.c optional scd isa dev/si/si.c optional si dev/si/si2_z280.c optional si dev/si/si3_t225.c optional si dev/si/si_eisa.c optional si eisa dev/si/si_isa.c optional si isa dev/si/si_pci.c optional si pci dev/sio/sio_pccard.c optional sio card dev/sio/sio_pccard.c optional sio pccard dev/sio/sio_pci.c optional sio pci dev/sio/sio_puc.c optional sio puc pci dev/smbus/smbus_if.m optional smbus dev/smbus/smb.c optional smb dev/smbus/smbconf.c optional smbus dev/smbus/smbus.c optional smbus dev/sn/if_sn.c optional sn dev/sn/if_sn_isa.c optional sn isa dev/sn/if_sn_pccard.c optional sn card dev/sn/if_sn_pccard.c optional sn pccard dev/snp/snp.c optional snp dev/sound/isa/ad1816.c optional pcm isa dev/sound/isa/es1888.c optional pcm isa dev/sound/isa/ess.c optional pcm isa dev/sound/isa/gusc.c optional gusc isa dev/sound/isa/gusc.c optional pcm isa dev/sound/isa/mss.c optional pcm isa dev/sound/isa/sb16.c optional pcm isa dev/sound/isa/sb8.c optional pcm isa dev/sound/isa/sbc.c optional pcm isa dev/sound/isa/sbc.c optional sbc isa dev/sound/isa/sndbuf_dma.c optional pcm isa dev/sound/pci/als4000.c optional pcm pci #dev/sound/pci/au88x0.c optional pcm pci dev/sound/pci/cmi.c optional pcm pci dev/sound/pci/cs4281.c optional pcm pci dev/sound/pci/csa.c optional csa pci dev/sound/pci/csa.c optional pcm pci dev/sound/pci/csapcm.c optional pcm pci dev/sound/pci/ds1.c optional pcm pci dev/sound/pci/emu10k1.c optional pcm pci dependency "emu10k1-alsa%diked.h" dev/sound/pci/es137x.c optional pcm pci dev/sound/pci/fm801.c optional pcm pci dev/sound/pci/ich.c optional pcm pci dev/sound/pci/maestro.c optional pcm pci dev/sound/pci/neomagic.c optional pcm pci dev/sound/pci/solo.c optional pcm pci dev/sound/pci/t4dwave.c optional pcm pci dev/sound/pci/via8233.c optional pcm pci dev/sound/pci/via82c686.c optional pcm pci dev/sound/pci/vibes.c optional pcm pci #dev/sound/pci/vortex1.c optional pcm pci dev/sound/pcm/ac97.c optional pcm dev/sound/pcm/ac97_patch.c optional pcm dev/sound/pcm/ac97_if.m optional pcm dev/sound/pcm/buffer.c optional pcm dev/sound/pcm/channel.c optional pcm dev/sound/pcm/channel_if.m optional pcm dev/sound/pcm/dsp.c optional pcm dev/sound/pcm/fake.c optional pcm dev/sound/pcm/feeder.c optional pcm dev/sound/pcm/feeder_if.m optional pcm dev/sound/pcm/feeder_fmt.c optional pcm dev/sound/pcm/feeder_rate.c optional pcm dev/sound/pcm/mixer.c optional pcm dev/sound/pcm/mixer_if.m optional pcm dev/sound/pcm/sndstat.c optional pcm dev/sound/pcm/sound.c optional pcm dev/sound/pcm/vchan.c optional pcm #dev/sound/usb/upcm.c optional pcm usb dev/sound/usb/uaudio.c optional pcm usb dev/sound/usb/uaudio_pcm.c optional pcm usb dev/sr/if_sr.c optional sr dev/sr/if_sr_pci.c optional sr pci dev/streams/streams.c optional streams dev/stg/tmc18c30.c optional stg dev/stg/tmc18c30_subr.c optional stg dev/stg/tmc18c30_pccard.c optional stg card dev/stg/tmc18c30_pccard.c optional stg pccard dev/stg/tmc18c30_pci.c optional stg pci dev/stg/tmc18c30_isa.c optional stg isa dev/sx/sx.c optional sx dev/sx/sx_util.c optional sx #dev/sx/sx_isa.c optional sx isa dev/sx/sx_pci.c optional sx pci dev/sym/sym_hipd.c optional sym \ dependency "$S/dev/sym/sym_{conf,defs}.h" dev/syscons/blank/blank_saver.c optional blank_saver dev/syscons/daemon/daemon_saver.c optional daemon_saver dev/syscons/fade/fade_saver.c optional fade_saver dev/syscons/fire/fire_saver.c optional fire_saver dev/syscons/green/green_saver.c optional green_saver dev/syscons/logo/logo_saver.c optional logo_saver dev/syscons/logo/logo.c optional logo_saver dev/syscons/rain/rain_saver.c optional rain_saver dev/syscons/star/star_saver.c optional star_saver dev/syscons/warp/warp_saver.c optional warp_saver dev/tdfx/tdfx_pci.c optional tdfx pci dev/trm/trm.c optional trm dev/twa/twa.c optional twa dev/twa/twa_cam.c optional twa dev/twa/twa_freebsd.c optional twa dev/twa/twa_fwimg.c optional twa dev/twa/twa_globals.c optional twa dev/twe/twe.c optional twe dev/twe/twe_freebsd.c optional twe dev/tx/if_tx.c optional tx dev/txp/if_txp.c optional txp dev/uart/uart_if.m optional uart dev/uart/uart_bus_acpi.c optional uart acpi dev/uart/uart_bus_ebus.c optional uart ebus dev/uart/uart_bus_isa.c optional uart isa #dev/uart/uart_bus_cbus.c optional uart cbus dev/uart/uart_bus_pccard.c optional uart pccard dev/uart/uart_bus_pci.c optional uart cardbus dev/uart/uart_bus_pci.c optional uart pci dev/uart/uart_bus_puc.c optional uart puc dev/uart/uart_core.c optional uart dev/uart/uart_dbg.c optional uart gdb dev/uart/uart_dev_i8251.c optional uart dev/uart/uart_dev_ns8250.c optional uart dev/uart/uart_dev_sab82532.c optional uart dev/uart/uart_dev_z8530.c optional uart dev/uart/uart_subr.c optional uart dev/uart/uart_tty.c optional uart dev/ubsec/ubsec.c optional ubsec # # USB support dev/usb/usb_if.m optional usb dev/usb/hid.c optional usb dev/usb/if_aue.c optional aue dev/usb/if_axe.c optional axe dev/usb/if_cue.c optional cue dev/usb/if_udav.c optional udav dev/usb/if_kue.c optional kue dev/usb/if_rue.c optional rue dev/usb/ehci.c optional ehci dev/usb/ehci_pci.c optional ehci pci dev/usb/ohci.c optional ohci dev/usb/ohci_pci.c optional ohci pci dev/usb/ubsa.c optional ubsa ucom dev/usb/ubser.c optional ubser dev/usb/ucom.c optional ucom dev/usb/udbp.c optional udbp dev/usb/ufm.c optional ufm dev/usb/uftdi.c optional uftdi ucom dev/usb/ugen.c optional ugen dev/usb/uhci.c optional uhci dev/usb/uhci_pci.c optional uhci pci dev/usb/uhid.c optional uhid dev/usb/uhub.c optional usb dev/usb/ukbd.c optional ukbd dev/usb/ulpt.c optional ulpt dev/usb/umass.c optional umass dev/usb/umct.c optional umct dev/usb/umodem.c optional umodem dev/usb/ums.c optional ums dev/usb/uplcom.c optional uplcom ucom dev/usb/urio.c optional urio dev/usb/uscanner.c optional uscanner dev/usb/uvisor.c optional uvisor ucom dev/usb/uvscom.c optional uvscom ucom dev/usb/usb.c optional usb dev/usb/usb_ethersubr.c optional usb dev/usb/usb_mem.c optional usb dev/usb/usb_quirks.c optional usb dev/usb/usb_subr.c optional usb dev/usb/usbdi.c optional usb dev/usb/usbdi_util.c optional usb dev/utopia/utopia.c optional utopia dev/vinum/vinum.c optional vinum dev/vinum/vinumconfig.c optional vinum dev/vinum/vinumdaemon.c optional vinum dev/vinum/vinuminterrupt.c optional vinum dev/vinum/vinumio.c optional vinum dev/vinum/vinumioctl.c optional vinum dev/vinum/vinumlock.c optional vinum dev/vinum/vinummemory.c optional vinum dev/vinum/vinumparser.c optional vinum dev/vinum/vinumraid5.c optional vinum dev/vinum/vinumrequest.c optional vinum dev/vinum/vinumrevive.c optional vinum dev/vinum/vinumstate.c optional vinum dev/vinum/vinumutil.c optional vinum dev/vx/if_vx.c optional vx dev/vx/if_vx_eisa.c optional vx eisa dev/vx/if_vx_pci.c optional vx pci #dev/wlp/if_wlp.c optional wlp card dev/watchdog/watchdog.c standard dev/wds/wd7000.c optional wds isa dev/wi/if_wi.c optional wi dev/wi/if_wi_pccard.c optional wi pccard dev/wi/if_wi_pccard.c optional wi card dev/wi/if_wi_pci.c optional wi pci dev/wl/if_wl.c optional wl isa dev/xe/if_xe.c optional xe dev/xe/if_xe_pccard.c optional xe card dev/xe/if_xe_pccard.c optional xe pccard dev/zs/zs.c optional zs dev/zs/zs_sbus.c optional zs fhc dev/zs/zs_sbus.c optional zs sbus fs/deadfs/dead_vnops.c standard fs/devfs/devfs_devs.c standard fs/devfs/devfs_rule.c standard fs/devfs/devfs_vfsops.c standard fs/devfs/devfs_vnops.c standard fs/fdescfs/fdesc_vfsops.c optional fdescfs fs/fdescfs/fdesc_vnops.c optional fdescfs fs/fifofs/fifo_vnops.c standard fs/hpfs/hpfs_alsubr.c optional hpfs fs/hpfs/hpfs_hash.c optional hpfs fs/hpfs/hpfs_lookup.c optional hpfs fs/hpfs/hpfs_subr.c optional hpfs fs/hpfs/hpfs_vfsops.c optional hpfs fs/hpfs/hpfs_vnops.c optional hpfs fs/msdosfs/msdosfs_conv.c optional msdosfs fs/msdosfs/msdosfs_denode.c optional msdosfs fs/msdosfs/msdosfs_fat.c optional msdosfs fs/msdosfs/msdosfs_lookup.c optional msdosfs fs/msdosfs/msdosfs_vfsops.c optional msdosfs fs/msdosfs/msdosfs_vnops.c optional msdosfs fs/msdosfs/msdosfs_fileno.c optional msdosfs_large fs/msdosfs/msdosfs_iconv.c optional msdosfs_iconv fs/ntfs/ntfs_compr.c optional ntfs fs/ntfs/ntfs_ihash.c optional ntfs fs/ntfs/ntfs_subr.c optional ntfs fs/ntfs/ntfs_vfsops.c optional ntfs fs/ntfs/ntfs_vnops.c optional ntfs fs/ntfs/ntfs_iconv.c optional ntfs_iconv fs/nullfs/null_subr.c optional nullfs fs/nullfs/null_vfsops.c optional nullfs fs/nullfs/null_vnops.c optional nullfs fs/nwfs/nwfs_io.c optional nwfs fs/nwfs/nwfs_ioctl.c optional nwfs fs/nwfs/nwfs_node.c optional nwfs fs/nwfs/nwfs_subr.c optional nwfs fs/nwfs/nwfs_vfsops.c optional nwfs fs/nwfs/nwfs_vnops.c optional nwfs fs/portalfs/portal_vfsops.c optional portalfs fs/portalfs/portal_vnops.c optional portalfs fs/procfs/procfs.c optional procfs fs/procfs/procfs_ctl.c optional procfs fs/procfs/procfs_dbregs.c optional procfs fs/procfs/procfs_fpregs.c optional procfs fs/procfs/procfs_ioctl.c optional procfs fs/procfs/procfs_map.c optional procfs fs/procfs/procfs_mem.c optional procfs fs/procfs/procfs_note.c optional procfs fs/procfs/procfs_regs.c optional procfs fs/procfs/procfs_rlimit.c optional procfs fs/procfs/procfs_status.c optional procfs fs/procfs/procfs_type.c optional procfs fs/pseudofs/pseudofs.c optional pseudofs fs/pseudofs/pseudofs_fileno.c optional pseudofs fs/pseudofs/pseudofs_vncache.c optional pseudofs fs/pseudofs/pseudofs_vnops.c optional pseudofs fs/smbfs/smbfs_io.c optional smbfs fs/smbfs/smbfs_node.c optional smbfs fs/smbfs/smbfs_smb.c optional smbfs fs/smbfs/smbfs_subr.c optional smbfs fs/smbfs/smbfs_vfsops.c optional smbfs fs/smbfs/smbfs_vnops.c optional smbfs fs/specfs/spec_vnops.c standard fs/udf/udf_iconv.c optional udf_iconv fs/udf/udf_vfsops.c optional udf fs/udf/udf_vnops.c optional udf fs/udf/osta.c optional udf fs/umapfs/umap_subr.c optional umapfs fs/umapfs/umap_vfsops.c optional umapfs fs/umapfs/umap_vnops.c optional umapfs fs/unionfs/union_subr.c optional unionfs fs/unionfs/union_vfsops.c optional unionfs fs/unionfs/union_vnops.c optional unionfs gdb/gdb_main.c optional gdb gdb/gdb_packet.c optional gdb geom/bde/g_bde.c optional geom_bde geom/bde/g_bde_crypt.c optional geom_bde geom/bde/g_bde_lock.c optional geom_bde geom/bde/g_bde_work.c optional geom_bde crypto/rijndael/rijndael-alg-fst.c optional geom_bde crypto/rijndael/rijndael-api-fst.c optional geom_bde crypto/sha2/sha2.c optional geom_bde geom/concat/g_concat.c optional geom_concat geom/gate/g_gate.c optional geom_gate geom/label/g_label.c optional geom_label geom/label/g_label_iso9660.c optional geom_label geom/label/g_label_msdosfs.c optional geom_label geom/label/g_label_ufs.c optional geom_label geom/nop/g_nop.c optional geom_nop geom/stripe/g_stripe.c optional geom_stripe geom/geom_aes.c optional geom_aes geom/geom_apple.c optional geom_apple geom/geom_bsd.c optional geom_bsd geom/geom_bsd_enc.c optional geom_bsd geom/geom_ccd.c optional ccd geom/geom_ccd.c optional geom_ccd geom/geom_ctl.c standard geom/geom_dev.c standard geom/geom_disk.c standard geom/geom_dump.c standard geom/geom_event.c standard geom/geom_fox.c optional geom_fox geom/geom_gpt.c optional geom_gpt geom/geom_io.c standard geom/geom_kern.c standard geom/geom_mbr.c optional geom_mbr geom/geom_mbr_enc.c optional geom_mbr geom/geom_mirror.c optional geom_mirror geom/geom_pc98.c optional geom_pc98 geom/geom_pc98_enc.c optional geom_pc98 geom/geom_slice.c standard geom/geom_subr.c standard geom/geom_sunlabel.c optional geom_sunlabel geom/geom_sunlabel_enc.c optional geom_sunlabel geom/geom_vol_ffs.c optional geom_vol gnu/ext2fs/ext2_alloc.c optional ext2fs \ warning "kernel contains GPL contaminated ext2fs filesystem" gnu/ext2fs/ext2_balloc.c optional ext2fs gnu/ext2fs/ext2_bmap.c optional ext2fs gnu/ext2fs/ext2_ihash.c optional ext2fs gnu/ext2fs/ext2_inode.c optional ext2fs gnu/ext2fs/ext2_inode_cnv.c optional ext2fs gnu/ext2fs/ext2_linux_balloc.c optional ext2fs gnu/ext2fs/ext2_linux_ialloc.c optional ext2fs gnu/ext2fs/ext2_lookup.c optional ext2fs gnu/ext2fs/ext2_subr.c optional ext2fs gnu/ext2fs/ext2_vfsops.c optional ext2fs gnu/ext2fs/ext2_vnops.c optional ext2fs # # isdn4bsd device drivers # i4b/driver/i4b_trace.c count i4btrc i4b/driver/i4b_rbch.c count i4brbch i4b/driver/i4b_tel.c count i4btel i4b/driver/i4b_ipr.c count i4bipr net/slcompress.c optional i4bipr i4b/driver/i4b_ctl.c optional i4bctl i4b/driver/i4b_ing.c count i4bing i4b/driver/i4b_isppp.c count i4bisppp net/slcompress.c optional i4bisppp # # isdn4bsd CAPI driver # i4b/capi/capi_l4if.c optional i4bcapi i4b/capi/capi_llif.c optional i4bcapi i4b/capi/capi_msgs.c optional i4bcapi # # isdn4bsd AVM B1/T1 CAPI driver # i4b/capi/iavc/iavc_pci.c optional iavc i4bcapi pci i4b/capi/iavc/iavc_isa.c optional iavc i4bcapi isa i4b/capi/iavc/iavc_lli.c optional iavc i4bcapi i4b/capi/iavc/iavc_card.c optional iavc i4bcapi # # isdn4bsd support # i4b/layer2/i4b_mbuf.c optional i4btrc # # isdn4bsd Q.921 handler # i4b/layer2/i4b_l2.c optional i4bq921 i4b/layer2/i4b_l2fsm.c optional i4bq921 i4b/layer2/i4b_uframe.c optional i4bq921 i4b/layer2/i4b_tei.c optional i4bq921 i4b/layer2/i4b_sframe.c optional i4bq921 i4b/layer2/i4b_iframe.c optional i4bq921 i4b/layer2/i4b_l2timer.c optional i4bq921 i4b/layer2/i4b_util.c optional i4bq921 i4b/layer2/i4b_lme.c optional i4bq921 # # isdn4bsd Q.931 handler # i4b/layer3/i4b_q931.c optional i4bq931 i4b/layer3/i4b_l3fsm.c optional i4bq931 i4b/layer3/i4b_l3timer.c optional i4bq931 i4b/layer3/i4b_l2if.c optional i4bq931 i4b/layer3/i4b_l4if.c optional i4bq931 i4b/layer3/i4b_q932fac.c optional i4bq931 # # isdn4bsd control device driver, interface to isdnd # i4b/layer4/i4b_i4bdrv.c optional i4b i4b/layer4/i4b_l4.c optional i4b i4b/layer4/i4b_l4mgmt.c optional i4b i4b/layer4/i4b_l4timer.c optional i4b # isa/isa_if.m standard isa/isa_common.c optional isa isa/isahint.c optional isa isa/orm.c optional isa isa/pnp.c optional isa isa/pnpparse.c optional isa isofs/cd9660/cd9660_bmap.c optional cd9660 isofs/cd9660/cd9660_lookup.c optional cd9660 isofs/cd9660/cd9660_node.c optional cd9660 isofs/cd9660/cd9660_rrip.c optional cd9660 isofs/cd9660/cd9660_util.c optional cd9660 isofs/cd9660/cd9660_vfsops.c optional cd9660 isofs/cd9660/cd9660_vnops.c optional cd9660 isofs/cd9660/cd9660_iconv.c optional cd9660_iconv kern/imgact_elf.c standard kern/imgact_shell.c standard kern/inflate.c optional gzip kern/init_main.c standard kern/init_sysent.c standard kern/kern_acct.c standard kern/kern_acl.c standard kern/kern_alq.c optional alq kern/kern_clock.c standard kern/kern_condvar.c standard kern/kern_conf.c standard kern/kern_context.c standard kern/kern_descrip.c standard kern/kern_poll.c optional device_polling kern/kern_environment.c standard kern/kern_event.c standard kern/kern_exec.c standard kern/kern_exit.c standard kern/kern_fork.c standard kern/kern_idle.c standard kern/kern_intr.c standard kern/kern_jail.c standard kern/kern_thr.c standard kern/kern_kse.c standard kern/kern_kthread.c standard kern/kern_ktr.c optional ktr kern/kern_ktrace.c standard kern/kern_linker.c standard kern/kern_lock.c standard kern/kern_lockf.c standard kern/kern_mac.c standard kern/kern_malloc.c standard kern/kern_mbuf.c standard kern/kern_mib.c standard kern/kern_module.c standard kern/kern_mutex.c standard kern/kern_mtxpool.c standard kern/kern_ntptime.c standard kern/kern_physio.c standard kern/kern_proc.c standard kern/kern_prot.c standard kern/kern_resource.c standard kern/kern_sema.c standard kern/kern_shutdown.c standard kern/kern_sig.c standard kern/kern_subr.c standard kern/kern_switch.c standard kern/kern_sx.c standard kern/kern_synch.c standard kern/kern_syscalls.c standard kern/kern_sysctl.c standard kern/kern_tc.c standard kern/kern_thread.c standard kern/kern_time.c standard kern/kern_timeout.c standard kern/kern_umtx.c standard kern/kern_uuid.c standard kern/kern_xxx.c standard kern/link_elf.c standard kern/md4c.c optional netsmb kern/md5c.c standard kern/sched_4bsd.c optional sched_4bsd kern/sched_ule.c optional sched_ule kern/subr_autoconf.c standard kern/subr_blist.c standard kern/subr_bus.c standard kern/subr_clock.c optional genclock kern/subr_devstat.c standard kern/subr_disk.c standard kern/subr_eventhandler.c standard kern/subr_hints.c standard kern/subr_kdb.c standard kern/subr_kobj.c standard kern/subr_log.c standard kern/subr_mbpool.c optional libmbpool kern/subr_mchain.c optional libmchain kern/subr_module.c standard kern/subr_msgbuf.c standard kern/subr_param.c standard kern/subr_pcpu.c standard kern/subr_power.c standard kern/subr_prf.c standard kern/subr_prof.c standard kern/subr_rman.c standard kern/subr_sbuf.c standard kern/subr_scanf.c standard kern/subr_sleepqueue.c standard kern/subr_smp.c standard kern/subr_taskqueue.c standard kern/subr_trap.c standard kern/subr_turnstile.c standard kern/subr_witness.c optional witness kern/sys_generic.c standard kern/sys_pipe.c standard kern/sys_process.c standard kern/sys_socket.c standard kern/syscalls.c optional witness kern/sysv_ipc.c standard kern/sysv_msg.c optional sysvmsg kern/sysv_sem.c optional sysvsem kern/sysv_shm.c optional sysvshm kern/tty.c standard kern/tty_compat.c standard kern/tty_conf.c standard kern/tty_cons.c standard kern/tty_pty.c optional pty kern/tty_subr.c standard kern/tty_tty.c standard kern/uipc_accf.c optional inet kern/uipc_cow.c optional zero_copy_sockets kern/uipc_domain.c standard kern/uipc_jumbo.c standard kern/uipc_mbuf.c standard kern/uipc_mbuf2.c standard kern/uipc_proto.c standard kern/uipc_socket.c standard kern/uipc_socket2.c standard kern/uipc_syscalls.c standard kern/uipc_usrreq.c standard kern/vfs_aio.c optional vfs_aio kern/vfs_bio.c standard kern/vfs_cache.c standard kern/vfs_cluster.c standard kern/vfs_default.c standard kern/vfs_export.c standard kern/vfs_init.c standard kern/vfs_lookup.c standard kern/vfs_mount.c standard kern/vfs_subr.c standard kern/vfs_syscalls.c standard kern/vfs_vnops.c standard # # These files in libkern/ are those needed by all architectures. Some # of the files in libkern/ are only needed on some architectures, e.g., # libkern/divdi3.c is needed by i386 but not alpha. Also, some of these # routines may be optimized for a particular platform. In either case, # the file should be moved to conf/files. from here. # libkern/arc4random.c standard libkern/bcd.c standard libkern/bsearch.c standard libkern/crc32.c standard libkern/iconv.c optional libiconv libkern/iconv_converter_if.m optional libiconv libkern/iconv_xlat.c optional libiconv libkern/iconv_xlat16.c optional libiconv libkern/index.c standard libkern/inet_ntoa.c standard libkern/mcount.c optional profiling-routine libkern/qsort.c standard libkern/fnmatch.c standard libkern/random.c standard libkern/rindex.c standard libkern/scanc.c standard libkern/skpc.c standard libkern/strcat.c standard libkern/strcmp.c standard libkern/strcpy.c standard libkern/strdup.c standard libkern/strlcat.c standard libkern/strlcpy.c standard libkern/strlen.c standard libkern/strncmp.c standard libkern/strncpy.c standard libkern/strsep.c standard libkern/strtol.c standard libkern/strtoq.c standard libkern/strtoul.c standard libkern/strtouq.c standard libkern/strvalid.c standard net/bpf.c standard net/bpf_filter.c optional bpf net/bridge.c optional bridge net/bsd_comp.c optional ppp_bsdcomp net/if.c standard net/if_arcsubr.c optional arcnet net/if_atmsubr.c optional atm net/if_clone.c standard net/if_disc.c optional disc net/if_ef.c optional ef net/if_ethersubr.c optional ether net/if_faith.c optional faith net/if_fddisubr.c optional fddi net/if_fwsubr.c optional firewire net/if_gif.c optional gif net/if_gre.c optional gre net/if_iso88025subr.c optional token net/if_loop.c optional loop net/if_media.c standard net/if_mib.c standard net/if_ppp.c optional ppp net/if_sl.c optional sl net/if_spppsubr.c optional sppp net/if_spppsubr.c optional i4bisppp net/if_stf.c optional stf net/if_tun.c optional tun net/if_tap.c optional tap net/if_vlan.c optional vlan net/net_osdep.c standard net/netisr.c standard net/ppp_deflate.c optional ppp_deflate net/ppp_tty.c optional ppp net/pfil.c optional pfil_hooks net/pfil.c optional ipfilter net/radix.c standard net/raw_cb.c standard net/raw_usrreq.c standard net/route.c standard net/rtsock.c standard net/slcompress.c optional ppp net/slcompress.c optional sl net/slcompress.c optional sppp net/zlib.c optional ppp_deflate net/zlib.c optional ipsec net/zlib.c optional crypto net80211/ieee80211.c optional wlan net80211/ieee80211_crypto.c optional wlan net80211/ieee80211_input.c optional wlan net80211/ieee80211_ioctl.c optional wlan net80211/ieee80211_node.c optional wlan net80211/ieee80211_output.c optional wlan net80211/ieee80211_proto.c optional wlan netatalk/aarp.c optional netatalk netatalk/at_control.c optional netatalk netatalk/at_proto.c optional netatalk netatalk/at_rmx.c optional netatalkdebug netatalk/ddp_input.c optional netatalk netatalk/ddp_output.c optional netatalk netatalk/ddp_pcb.c optional netatalk netatalk/ddp_usrreq.c optional netatalk netatm/atm_aal5.c optional atm_core netatm/atm_cm.c optional atm_core netatm/atm_device.c optional atm_core netatm/atm_if.c optional atm_core netatm/atm_proto.c optional atm_core netatm/atm_signal.c optional atm_core netatm/atm_socket.c optional atm_core netatm/atm_subr.c optional atm_core netatm/atm_usrreq.c optional atm_core netatm/ipatm/ipatm_event.c optional atm_ip atm_core netatm/ipatm/ipatm_if.c optional atm_ip atm_core netatm/ipatm/ipatm_input.c optional atm_ip atm_core netatm/ipatm/ipatm_load.c optional atm_ip atm_core netatm/ipatm/ipatm_output.c optional atm_ip atm_core netatm/ipatm/ipatm_usrreq.c optional atm_ip atm_core netatm/ipatm/ipatm_vcm.c optional atm_ip atm_core netatm/sigpvc/sigpvc_if.c optional atm_sigpvc atm_core netatm/sigpvc/sigpvc_subr.c optional atm_sigpvc atm_core netatm/spans/spans_arp.c optional atm_spans atm_core \ dependency "spans_xdr.h" netatm/spans/spans_cls.c optional atm_spans atm_core netatm/spans/spans_if.c optional atm_spans atm_core netatm/spans/spans_kxdr.c optional atm_spans atm_core netatm/spans/spans_msg.c optional atm_spans atm_core netatm/spans/spans_print.c optional atm_spans atm_core netatm/spans/spans_proto.c optional atm_spans atm_core netatm/spans/spans_subr.c optional atm_spans atm_core netatm/spans/spans_util.c optional atm_spans atm_core spans_xdr.h optional atm_spans atm_core \ before-depend \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "rpcgen -h -C $S/netatm/spans/spans_xdr.x | grep -v rpc/rpc.h > spans_xdr.h" \ clean "spans_xdr.h" \ no-obj no-implicit-rule spans_xdr.c optional atm_spans atm_core \ before-depend \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "rpcgen -c -C $S/netatm/spans/spans_xdr.x | grep -v rpc/rpc.h > spans_xdr.c" \ clean "spans_xdr.c" \ no-obj no-implicit-rule local spans_xdr.o optional atm_spans atm_core \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "${NORMAL_C}" \ no-implicit-rule local netatm/uni/q2110_sigaa.c optional atm_uni atm_core netatm/uni/q2110_sigcpcs.c optional atm_uni atm_core netatm/uni/q2110_subr.c optional atm_uni atm_core netatm/uni/qsaal1_sigaa.c optional atm_uni atm_core netatm/uni/qsaal1_sigcpcs.c optional atm_uni atm_core netatm/uni/qsaal1_subr.c optional atm_uni atm_core netatm/uni/sscf_uni.c optional atm_uni atm_core netatm/uni/sscf_uni_lower.c optional atm_uni atm_core netatm/uni/sscf_uni_upper.c optional atm_uni atm_core netatm/uni/sscop.c optional atm_uni atm_core netatm/uni/sscop_lower.c optional atm_uni atm_core netatm/uni/sscop_pdu.c optional atm_uni atm_core netatm/uni/sscop_sigaa.c optional atm_uni atm_core netatm/uni/sscop_sigcpcs.c optional atm_uni atm_core netatm/uni/sscop_subr.c optional atm_uni atm_core netatm/uni/sscop_timer.c optional atm_uni atm_core netatm/uni/sscop_upper.c optional atm_uni atm_core netatm/uni/uni_load.c optional atm_uni atm_core netatm/uni/uniarp.c optional atm_uni atm_core netatm/uni/uniarp_cache.c optional atm_uni atm_core netatm/uni/uniarp_input.c optional atm_uni atm_core netatm/uni/uniarp_output.c optional atm_uni atm_core netatm/uni/uniarp_timer.c optional atm_uni atm_core netatm/uni/uniarp_vcm.c optional atm_uni atm_core netatm/uni/uniip.c optional atm_uni atm_core netatm/uni/unisig_decode.c optional atm_uni atm_core netatm/uni/unisig_encode.c optional atm_uni atm_core netatm/uni/unisig_if.c optional atm_uni atm_core netatm/uni/unisig_mbuf.c optional atm_uni atm_core netatm/uni/unisig_msg.c optional atm_uni atm_core netatm/uni/unisig_print.c optional atm_uni atm_core netatm/uni/unisig_proto.c optional atm_uni atm_core netatm/uni/unisig_sigmgr_state.c optional atm_uni atm_core netatm/uni/unisig_subr.c optional atm_uni atm_core netatm/uni/unisig_util.c optional atm_uni atm_core netatm/uni/unisig_vc_state.c optional atm_uni atm_core netgraph/atm/atmpif/ng_atmpif.c optional netgraph_atm_atmpif netgraph/atm/atmpif/ng_atmpif_harp.c optional netgraph_atm_atmpif netgraph/atm/ngatmbase.c optional ngatm_atmbase contrib/ngatm/netnatm/misc/unimsg_common.c optional ngatm_atmbase contrib/ngatm/netnatm/misc/straddr.c optional ngatm_atmbase contrib/ngatm/netnatm/msg/traffic.c optional ngatm_atmbase contrib/ngatm/netnatm/msg/uni_ie.c optional ngatm_atmbase contrib/ngatm/netnatm/msg/uni_msg.c optional ngatm_atmbase netgraph/atm/ng_atm.c optional ngatm_atm netgraph/atm/sscfu/ng_sscfu.c optional ngatm_sscfu contrib/ngatm/netnatm/saal/saal_sscfu.c optional ngatm_sscfu netgraph/atm/sscop/ng_sscop.c optional ngatm_sscop contrib/ngatm/netnatm/saal/saal_sscop.c optional ngatm_sscop netgraph/atm/uni/ng_uni.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_call.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_coord.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_party.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_print.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_reset.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_uni.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_unimsgcpy.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_verify.c optional ngatm_uni netgraph/bluetooth/common/ng_bluetooth.c optional netgraph_bluetooth netgraph/bluetooth/drivers/bt3c/ng_bt3c_pccard.c optional netgraph_bluetooth_bt3c netgraph/bluetooth/drivers/h4/ng_h4.c optional netgraph_bluetooth_h4 netgraph/bluetooth/drivers/ubt/ng_ubt.c optional netgraph_bluetooth_ubt netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c optional netgraph_bluetooth_ubtbcmfw netgraph/bluetooth/hci/ng_hci_cmds.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_evnt.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_main.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_misc.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_ulpi.c optional netgraph_bluetooth_hci netgraph/bluetooth/l2cap/ng_l2cap_cmds.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_evnt.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_llpi.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_main.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_misc.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_ulpi.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/socket/ng_btsocket.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_hci_raw.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_l2cap.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_rfcomm.c optional netgraph_bluetooth_socket netgraph/ng_UI.c optional netgraph_UI netgraph/ng_async.c optional netgraph_async netgraph/ng_atmllc.c optional netgraph_atmllc netgraph/ng_base.c optional netgraph netgraph/ng_bpf.c optional netgraph_bpf net/bpf_filter.c optional netgraph_bpf netgraph/ng_bridge.c optional netgraph_bridge netgraph/ng_cisco.c optional netgraph_cisco netgraph/ng_device.c optional netgraph_device netgraph/ng_echo.c optional netgraph_echo netgraph/ng_eiface.c optional netgraph_eiface netgraph/ng_ether.c optional netgraph_ether netgraph/ng_fec.c optional netgraph_fec netgraph/ng_frame_relay.c optional netgraph_frame_relay netgraph/ng_gif.c optional netgraph_gif netgraph/ng_gif_demux.c optional netgraph_gif_demux netgraph/ng_hole.c optional netgraph_hole netgraph/ng_iface.c optional netgraph_iface netgraph/ng_ip_input.c optional netgraph_ip_input netgraph/ng_ksocket.c optional netgraph_ksocket netgraph/ng_lmi.c optional netgraph_lmi netgraph/ng_l2tp.c optional netgraph_l2tp netgraph/ng_mppc.c optional netgraph_mppc_compression netgraph/ng_mppc.c optional netgraph_mppc_encryption crypto/rc4/rc4.c optional wlan crypto/rc4/rc4.c optional netgraph_mppc_encryption crypto/sha1.c optional netgraph_mppc_encryption netgraph/ng_one2many.c optional netgraph_one2many netgraph/ng_parse.c optional netgraph netgraph/ng_ppp.c optional netgraph_ppp netgraph/ng_pppoe.c optional netgraph_pppoe netgraph/ng_pptpgre.c optional netgraph_pptpgre netgraph/ng_rfc1490.c optional netgraph_rfc1490 netgraph/ng_socket.c optional netgraph_socket netgraph/ng_split.c optional netgraph_split netgraph/ng_sppp.c optional netgraph_sppp netgraph/ng_tee.c optional netgraph_tee netgraph/ng_tty.c optional netgraph_tty netgraph/ng_vjc.c optional netgraph_vjc net/slcompress.c optional netgraph_vjc netinet/accf_data.c optional accept_filter_data netinet/accf_http.c optional accept_filter_http netinet/if_atm.c optional atm netinet/if_ether.c optional ether netinet/igmp.c optional inet netinet/in.c optional inet netinet/in_gif.c optional gif inet netinet/ip_gre.c optional gre inet netinet/ip_id.c optional inet netinet/in_pcb.c optional inet netinet/in_proto.c optional inet netinet/in_rmx.c optional inet netinet/ip_divert.c optional ipdivert netinet/ip_dummynet.c optional dummynet netinet/ip_ecn.c optional inet netinet/ip_ecn.c optional inet6 netinet/ip_encap.c optional inet netinet/ip_encap.c optional inet6 netinet/ip_fastfwd.c optional inet netinet/ip_fw2.c optional ipfirewall netinet/ip_icmp.c optional inet netinet/ip_input.c optional inet netinet/ip_mroute.c optional mrouting netinet/ip_output.c optional inet netinet/raw_ip.c optional inet netinet/tcp_debug.c optional tcpdebug netinet/tcp_hostcache.c optional inet netinet/tcp_input.c optional inet netinet/tcp_output.c optional inet netinet/tcp_sack.c optional inet netinet/tcp_subr.c optional inet netinet/tcp_syncache.c optional inet netinet/tcp_timer.c optional inet netinet/tcp_usrreq.c optional inet netinet/udp_usrreq.c optional inet netinet6/ah_aesxcbcmac.c optional ipsec netinet6/ah_core.c optional ipsec netinet6/ah_input.c optional ipsec netinet6/ah_output.c optional ipsec netinet6/dest6.c optional inet6 netinet6/esp_aesctr.c optional ipsec ipsec_esp netinet6/esp_core.c optional ipsec ipsec_esp netinet6/esp_input.c optional ipsec ipsec_esp netinet6/esp_output.c optional ipsec ipsec_esp netinet6/esp_rijndael.c optional ipsec ipsec_esp netinet6/frag6.c optional inet6 netinet6/icmp6.c optional inet6 netinet6/in6.c optional inet6 netinet6/in6_cksum.c optional inet6 netinet6/in6_gif.c optional gif inet6 netinet6/in6_ifattach.c optional inet6 netinet6/in6_pcb.c optional inet6 netinet6/in6_prefix.c optional inet6 netinet6/in6_proto.c optional inet6 netinet6/in6_rmx.c optional inet6 netinet6/in6_src.c optional inet6 netinet6/ip6_forward.c optional inet6 netinet6/ip6_fw.c optional inet6 ipv6firewall netinet6/ip6_id.c optional inet6 netinet6/ip6_input.c optional inet6 netinet6/ip6_mroute.c optional inet6 netinet6/ip6_output.c optional inet6 netinet6/ipcomp_core.c optional ipsec netinet6/ipcomp_input.c optional ipsec netinet6/ipcomp_output.c optional ipsec netinet6/ipsec.c optional ipsec netinet6/mld6.c optional inet6 netinet6/nd6.c optional inet6 netinet6/nd6_nbr.c optional inet6 netinet6/nd6_rtr.c optional inet6 netinet6/raw_ip6.c optional inet6 netinet6/route6.c optional inet6 netinet6/scope6.c optional inet6 netinet6/udp6_output.c optional inet6 netinet6/udp6_usrreq.c optional inet6 netipsec/ipsec.c optional fast_ipsec netipsec/ipsec_input.c optional fast_ipsec netipsec/ipsec_mbuf.c optional fast_ipsec netipsec/ipsec_output.c optional fast_ipsec netipsec/key.c optional fast_ipsec netipsec/key_debug.c optional fast_ipsec netipsec/keysock.c optional fast_ipsec netipsec/xform_ah.c optional fast_ipsec netipsec/xform_esp.c optional fast_ipsec netipsec/xform_ipcomp.c optional fast_ipsec netipsec/xform_ipip.c optional fast_ipsec netipsec/xform_tcp.c optional fast_ipsec tcp_signature netipx/ipx.c optional ipx netipx/ipx_cksum.c optional ipx netipx/ipx_input.c optional ipx netipx/ipx_ip.c optional ipx netipx/ipx_outputfl.c optional ipx netipx/ipx_pcb.c optional ipx netipx/ipx_proto.c optional ipx netipx/ipx_usrreq.c optional ipx netipx/spx_debug.c optional ipx netipx/spx_usrreq.c optional ipx netkey/key.c optional ipsec netkey/key_debug.c optional ipsec netkey/keydb.c optional ipsec netkey/keysock.c optional ipsec netnatm/natm.c optional natm netnatm/natm_pcb.c optional natm netnatm/natm_proto.c optional natm netncp/ncp_conn.c optional ncp netncp/ncp_crypt.c optional ncp netncp/ncp_login.c optional ncp netncp/ncp_mod.c optional ncp netncp/ncp_ncp.c optional ncp netncp/ncp_nls.c optional ncp netncp/ncp_rq.c optional ncp netncp/ncp_sock.c optional ncp netncp/ncp_subr.c optional ncp netsmb/smb_conn.c optional netsmb netsmb/smb_crypt.c optional netsmb netsmb/smb_dev.c optional netsmb netsmb/smb_iod.c optional netsmb netsmb/smb_rq.c optional netsmb netsmb/smb_smb.c optional netsmb netsmb/smb_subr.c optional netsmb netsmb/smb_trantcp.c optional netsmb netsmb/smb_usr.c optional netsmb nfs/nfs_common.c optional nfsclient nfs/nfs_common.c optional nfsserver nfsclient/bootp_subr.c optional bootp nfsclient nfsclient/krpc_subr.c optional bootp nfsclient nfsclient/nfs_bio.c optional nfsclient nfsclient/nfs_diskless.c optional nfsclient nfs_root nfsclient/nfs_node.c optional nfsclient nfsclient/nfs_socket.c optional nfsclient nfsclient/nfs_subs.c optional nfsclient nfsclient/nfs_nfsiod.c optional nfsclient nfsclient/nfs_vfsops.c optional nfsclient nfsclient/nfs_vnops.c optional nfsclient nfsclient/nfs_lock.c optional nfsclient nfs4client/nfs4_socket.c optional nfsclient nfs4client/nfs4_vfsops.c optional nfsclient nfs4client/nfs4_vnops.c optional nfsclient nfs4client/nfs4_subs.c optional nfsclient nfs4client/nfs4_vfs_subs.c optional nfsclient nfs4client/nfs4_vn_subs.c optional nfsclient nfs4client/nfs4_dev.c optional nfsclient nfs4client/nfs4_idmap.c optional nfsclient rpc/rpcclnt.c optional nfsclient nfsserver/nfs_serv.c optional nfsserver nfsserver/nfs_srvsock.c optional nfsserver nfsserver/nfs_srvcache.c optional nfsserver nfsserver/nfs_srvsubs.c optional nfsserver nfsserver/nfs_syscalls.c optional nfsserver # crypto support opencrypto/cast.c optional crypto opencrypto/criov.c optional crypto opencrypto/crypto.c optional crypto opencrypto/cryptodev.c optional cryptodev opencrypto/cryptosoft.c optional crypto opencrypto/deflate.c optional crypto opencrypto/rmd160.c optional crypto opencrypto/rijndael.c optional crypto opencrypto/skipjack.c optional crypto opencrypto/xform.c optional crypto crypto/blowfish/bf_skey.c optional crypto crypto/des/des_ecb.c optional crypto crypto/des/des_setkey.c optional crypto crypto/sha1.c optional crypto crypto/sha2/sha2.c optional crypto pccard/pccard.c count card pccard/pccard_beep.c optional card pccard/pccard_nbk.c optional card pccard/pcic.c optional pcic card pccard/pcic_isa.c optional pcic card isa pccard/pcic_pci.c optional pcic card pci pci/agp.c optional agp pci pci/agp_if.m optional agp pci pci/alpm.c optional alpm pci pci/amdpm.c optional amdpm pci pci/amdpm.c optional nfpm pci pci/if_dc.c optional dc pci pci/if_de.c optional de pci pci/if_mn.c optional mn pci pci/if_pcn.c optional pcn pci pci/if_rl.c optional rl pci pci/if_sf.c optional sf pci pci/if_sis.c optional sis pci pci/if_sk.c optional sk pci pci/if_ste.c optional ste pci pci/if_ti.c optional ti pci pci/if_tl.c optional tl pci pci/if_vr.c optional vr pci pci/if_wb.c optional wb pci pci/if_xl.c optional xl pci pci/intpm.c optional intpm pci pci/ncr.c optional ncr pci pci/viapm.c optional viapm pci pci/xrpu.c optional xrpu pci posix4/ksched.c optional _kposix_priority_scheduling posix4/p1003_1b.c standard posix4/posix4_mib.c standard kern/uipc_sem.c optional p1003_1b_semaphores security/mac/mac_inet.c optional mac inet security/mac/mac_label.c optional mac security/mac/mac_net.c optional mac security/mac/mac_pipe.c optional mac security/mac/mac_process.c optional mac security/mac/mac_socket.c optional mac security/mac/mac_system.c optional mac security/mac/mac_vfs.c optional mac security/mac_biba/mac_biba.c optional mac_biba security/mac_bsdextended/mac_bsdextended.c optional mac_bsdextended security/mac_ifoff/mac_ifoff.c optional mac_ifoff security/mac_lomac/mac_lomac.c optional mac_lomac security/mac_mls/mac_mls.c optional mac_mls security/mac_none/mac_none.c optional mac_none security/mac_partition/mac_partition.c optional mac_partition security/mac_portacl/mac_portacl.c optional mac_portacl security/mac_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids security/mac_stub/mac_stub.c optional mac_stub security/mac_test/mac_test.c optional mac_test ufs/ffs/ffs_alloc.c optional ffs ufs/ffs/ffs_balloc.c optional ffs ufs/ffs/ffs_inode.c optional ffs ufs/ffs/ffs_snapshot.c optional ffs ufs/ffs/ffs_softdep.c optional softupdates ffs ufs/ffs/ffs_softdep_stub.c optional ffs ufs/ffs/ffs_subr.c optional ffs ufs/ffs/ffs_tables.c optional ffs ufs/ffs/ffs_vfsops.c optional ffs ufs/ffs/ffs_vnops.c optional ffs ufs/ffs/ffs_rawread.c optional directio ufs/ufs/ufs_acl.c optional ffs ufs/ufs/ufs_bmap.c optional ffs ufs/ufs/ufs_dirhash.c optional ffs ufs/ufs/ufs_extattr.c optional ffs ufs/ufs/ufs_ihash.c optional ffs ufs/ufs/ufs_inode.c optional ffs ufs/ufs/ufs_lookup.c optional ffs ufs/ufs/ufs_quota.c optional ffs ufs/ufs/ufs_vfsops.c optional ffs ufs/ufs/ufs_vnops.c optional ffs vm/default_pager.c standard vm/device_pager.c standard vm/phys_pager.c standard vm/swap_pager.c standard vm/vm_fault.c standard vm/vm_glue.c standard vm/vm_init.c standard vm/vm_kern.c standard vm/vm_map.c standard vm/vm_meter.c standard vm/vm_mmap.c standard vm/vm_object.c standard vm/vm_page.c standard vm/vm_pageq.c standard vm/vm_contig.c standard vm/vm_zeroidle.c standard vm/vm_pageout.c standard vm/vm_pager.c standard vm/vm_unix.c standard vm/uma_core.c standard vm/uma_dbg.c standard vm/vnode_pager.c standard Index: head/sys/ddb/db_access.c =================================================================== --- head/sys/ddb/db_access.c (revision 131951) +++ head/sys/ddb/db_access.c (revision 131952) @@ -1,101 +1,109 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. */ /* * Author: David B. Golub, Carnegie Mellon University * Date: 7/90 */ #include __FBSDID("$FreeBSD$"); #include +#include #include #include /* * Access unaligned data items on aligned (longword) * boundaries. */ static unsigned db_extend[] = { /* table for sign-extending */ 0, 0xFFFFFF80U, 0xFFFF8000U, 0xFF800000U }; db_expr_t db_get_value(addr, size, is_signed) db_addr_t addr; register int size; boolean_t is_signed; { char data[sizeof(u_int64_t)]; register db_expr_t value; register int i; - db_read_bytes(addr, size, data); + if (db_read_bytes(addr, size, data) != 0) { + db_printf("*** error reading from address %llx ***\n", + (long long)addr); + kdb_reenter(); + } value = 0; #if BYTE_MSF for (i = 0; i < size; i++) #else /* BYTE_LSF */ for (i = size - 1; i >= 0; i--) #endif { value = (value << 8) + (data[i] & 0xFF); } if (size < 4) { if (is_signed && (value & db_extend[size]) != 0) value |= db_extend[size]; } return (value); } void db_put_value(addr, size, value) db_addr_t addr; register int size; register db_expr_t value; { char data[sizeof(int)]; register int i; #if BYTE_MSF for (i = size - 1; i >= 0; i--) #else /* BYTE_LSF */ for (i = 0; i < size; i++) #endif { data[i] = value & 0xFF; value >>= 8; } - db_write_bytes(addr, size, data); + if (db_write_bytes(addr, size, data) != 0) { + db_printf("*** error writing to address %llx ***\n", + (long long)addr); + kdb_reenter(); + } } - Index: head/sys/ddb/db_break.c =================================================================== --- head/sys/ddb/db_break.c (revision 131951) +++ head/sys/ddb/db_break.c (revision 131952) @@ -1,412 +1,369 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. * */ /* * Author: David B. Golub, Carnegie Mellon University * Date: 7/90 */ /* * Breakpoints. */ #include __FBSDID("$FreeBSD$"); #include "opt_comconsole.h" #include #include #include #include #include #include #include #define NBREAKPOINTS 100 static struct db_breakpoint db_break_table[NBREAKPOINTS]; static db_breakpoint_t db_next_free_breakpoint = &db_break_table[0]; static db_breakpoint_t db_free_breakpoints = 0; static db_breakpoint_t db_breakpoint_list = 0; static db_breakpoint_t db_breakpoint_alloc(void); static void db_breakpoint_free(db_breakpoint_t bkpt); static void db_delete_breakpoint(vm_map_t map, db_addr_t addr); static db_breakpoint_t db_find_breakpoint(vm_map_t map, db_addr_t addr); static void db_list_breakpoints(void); static void db_set_breakpoint(vm_map_t map, db_addr_t addr, int count); static db_breakpoint_t db_breakpoint_alloc() { register db_breakpoint_t bkpt; if ((bkpt = db_free_breakpoints) != 0) { db_free_breakpoints = bkpt->link; return (bkpt); } if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) { db_printf("All breakpoints used.\n"); return (0); } bkpt = db_next_free_breakpoint; db_next_free_breakpoint++; return (bkpt); } static void db_breakpoint_free(bkpt) register db_breakpoint_t bkpt; { bkpt->link = db_free_breakpoints; db_free_breakpoints = bkpt; } static void db_set_breakpoint(map, addr, count) vm_map_t map; db_addr_t addr; int count; { register db_breakpoint_t bkpt; if (db_find_breakpoint(map, addr)) { db_printf("Already set.\n"); return; } bkpt = db_breakpoint_alloc(); if (bkpt == 0) { db_printf("Too many breakpoints.\n"); return; } bkpt->map = map; bkpt->address = addr; bkpt->flags = 0; bkpt->init_count = count; bkpt->count = count; bkpt->link = db_breakpoint_list; db_breakpoint_list = bkpt; } static void db_delete_breakpoint(map, addr) vm_map_t map; db_addr_t addr; { register db_breakpoint_t bkpt; register db_breakpoint_t *prev; for (prev = &db_breakpoint_list; (bkpt = *prev) != 0; prev = &bkpt->link) { if (db_map_equal(bkpt->map, map) && (bkpt->address == addr)) { *prev = bkpt->link; break; } } if (bkpt == 0) { db_printf("Not set.\n"); return; } db_breakpoint_free(bkpt); } static db_breakpoint_t db_find_breakpoint(map, addr) vm_map_t map; db_addr_t addr; { register db_breakpoint_t bkpt; for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) { if (db_map_equal(bkpt->map, map) && (bkpt->address == addr)) return (bkpt); } return (0); } db_breakpoint_t db_find_breakpoint_here(addr) db_addr_t addr; { return db_find_breakpoint(db_map_addr(addr), addr); } static boolean_t db_breakpoints_inserted = TRUE; #ifndef BKPT_WRITE #define BKPT_WRITE(addr, storage) \ do { \ *storage = db_get_value(addr, BKPT_SIZE, FALSE); \ db_put_value(addr, BKPT_SIZE, BKPT_SET(*storage)); \ } while (0) #endif #ifndef BKPT_CLEAR #define BKPT_CLEAR(addr, storage) \ db_put_value(addr, BKPT_SIZE, *storage) #endif void db_set_breakpoints() { register db_breakpoint_t bkpt; if (!db_breakpoints_inserted) { for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) if (db_map_current(bkpt->map)) { BKPT_WRITE(bkpt->address, &bkpt->bkpt_inst); } db_breakpoints_inserted = TRUE; } } void db_clear_breakpoints() { register db_breakpoint_t bkpt; if (db_breakpoints_inserted) { for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) if (db_map_current(bkpt->map)) { BKPT_CLEAR(bkpt->address, &bkpt->bkpt_inst); } db_breakpoints_inserted = FALSE; } } #ifdef SOFTWARE_SSTEP /* * Set a temporary breakpoint. * The instruction is changed immediately, * so the breakpoint does not have to be on the breakpoint list. */ db_breakpoint_t db_set_temp_breakpoint(addr) db_addr_t addr; { register db_breakpoint_t bkpt; bkpt = db_breakpoint_alloc(); if (bkpt == 0) { db_printf("Too many breakpoints.\n"); return 0; } bkpt->map = NULL; bkpt->address = addr; bkpt->flags = BKPT_TEMP; bkpt->init_count = 1; bkpt->count = 1; BKPT_WRITE(bkpt->address, &bkpt->bkpt_inst); return bkpt; } void db_delete_temp_breakpoint(bkpt) db_breakpoint_t bkpt; { BKPT_CLEAR(bkpt->address, &bkpt->bkpt_inst); db_breakpoint_free(bkpt); } #endif /* SOFTWARE_SSTEP */ /* * List breakpoints. */ static void db_list_breakpoints() { register db_breakpoint_t bkpt; if (db_breakpoint_list == 0) { db_printf("No breakpoints set\n"); return; } db_printf(" Map Count Address\n"); for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) { db_printf("%s%8p %5d ", db_map_current(bkpt->map) ? "*" : " ", (void *)bkpt->map, bkpt->init_count); db_printsym(bkpt->address, DB_STGY_PROC); db_printf("\n"); } } /* Delete breakpoint */ /*ARGSUSED*/ void db_delete_cmd(addr, have_addr, count, modif) db_expr_t addr; boolean_t have_addr; db_expr_t count; char * modif; { db_delete_breakpoint(db_map_addr(addr), (db_addr_t)addr); } /* Set breakpoint with skip count */ /*ARGSUSED*/ void db_breakpoint_cmd(addr, have_addr, count, modif) db_expr_t addr; boolean_t have_addr; db_expr_t count; char * modif; { if (count == -1) count = 1; db_set_breakpoint(db_map_addr(addr), (db_addr_t)addr, count); } /* list breakpoints */ void db_listbreak_cmd(dummy1, dummy2, dummy3, dummy4) db_expr_t dummy1; boolean_t dummy2; db_expr_t dummy3; char * dummy4; { db_list_breakpoints(); } /* * We want ddb to be usable before most of the kernel has been * initialized. In particular, current_thread() or kernel_map * (or both) may be null. */ boolean_t db_map_equal(map1, map2) vm_map_t map1, map2; { return ((map1 == map2) || ((map1 == NULL) && (map2 == kernel_map)) || ((map1 == kernel_map) && (map2 == NULL))); } boolean_t db_map_current(map) vm_map_t map; { #if 0 thread_t thread; return ((map == NULL) || (map == kernel_map) || (((thread = current_thread()) != NULL) && (map == thread->task->map))); #else return (1); #endif } vm_map_t db_map_addr(addr) vm_offset_t addr; { #if 0 thread_t thread; /* * We want to return kernel_map for all * non-user addresses, even when debugging * kernel tasks with their own maps. */ if ((VM_MIN_ADDRESS <= addr) && (addr < VM_MAX_ADDRESS) && ((thread = current_thread()) != NULL)) return thread->task->map; else #endif return kernel_map; } - -#ifdef ALT_BREAK_TO_DEBUGGER -/* - * Solaris implements a new BREAK which is initiated by a character sequence - * CR ~ ^b which is similar to a familiar pattern used on Sun servers by the - * Remote Console. - * - * Note that this function may be called from almost anywhere, with interrupts - * disabled and with unknown locks held, so it must not access data other than - * its arguments. Its up to the caller to ensure that the state variable is - * consistent. - */ - -#define KEY_CR 13 /* CR '\r' */ -#define KEY_TILDE 126 /* ~ */ -#define KEY_CRTLB 2 /* ^B */ - -int -db_alt_break(int data, int *state) -{ - int brk = 0; - - switch (data) { - case KEY_CR: - *state = KEY_TILDE; - break; - case KEY_TILDE: - if (*state == KEY_TILDE) - *state = KEY_CRTLB; - else - *state = 0; - break; - case KEY_CRTLB: - if (*state == KEY_CRTLB) - brk = 1; - /* FALLTHROUGH */ - default: - *state = 0; - break; - } - return (brk); -} -#endif Index: head/sys/ddb/db_command.c =================================================================== --- head/sys/ddb/db_command.c (revision 131951) +++ head/sys/ddb/db_command.c (revision 131952) @@ -1,662 +1,613 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. */ /* * Author: David B. Golub, Carnegie Mellon University * Date: 7/90 */ /* * Command dispatcher. */ #include __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Exported global variables */ boolean_t db_cmd_loop_done; db_addr_t db_dot; -jmp_buf db_jmpbuf; db_addr_t db_last_addr; db_addr_t db_prev; db_addr_t db_next; SET_DECLARE(db_cmd_set, struct command); SET_DECLARE(db_show_cmd_set, struct command); static db_cmdfcn_t db_fncall; -static db_cmdfcn_t db_gdb; static db_cmdfcn_t db_kill; static db_cmdfcn_t db_reset; static db_cmdfcn_t db_watchdog; /* XXX this is actually forward-static. */ extern struct command db_show_cmds[]; /* * if 'ed' style: 'dot' is set at start of last item printed, * and '+' points to next line. * Otherwise: 'dot' points to next item, '..' points to last. */ static boolean_t db_ed_style = TRUE; /* * Utility routine - discard tokens through end-of-line. */ void db_skip_to_eol() { int t; do { t = db_read_token(); } while (t != tEOL); } /* * Results of command search. */ #define CMD_UNIQUE 0 #define CMD_FOUND 1 #define CMD_NONE 2 #define CMD_AMBIGUOUS 3 #define CMD_HELP 4 static void db_cmd_list(struct command *table, struct command **aux_tablep, struct command **aux_tablep_end); static int db_cmd_search(char *name, struct command *table, struct command **aux_tablep, struct command **aux_tablep_end, struct command **cmdp); static void db_command(struct command **last_cmdp, struct command *cmd_table, struct command **aux_cmd_tablep, struct command **aux_cmd_tablep_end); /* * Search for command prefix. */ static int db_cmd_search(name, table, aux_tablep, aux_tablep_end, cmdp) char * name; struct command *table; struct command **aux_tablep; struct command **aux_tablep_end; struct command **cmdp; /* out */ { struct command *cmd; struct command **aux_cmdp; int result = CMD_NONE; for (cmd = table; cmd->name != 0; cmd++) { register char *lp; register char *rp; register int c; lp = name; rp = cmd->name; while ((c = *lp) == *rp) { if (c == 0) { /* complete match */ *cmdp = cmd; return (CMD_UNIQUE); } lp++; rp++; } if (c == 0) { /* end of name, not end of command - partial match */ if (result == CMD_FOUND) { result = CMD_AMBIGUOUS; /* but keep looking for a full match - this lets us match single letters */ } else { *cmdp = cmd; result = CMD_FOUND; } } } if (result == CMD_NONE && aux_tablep != 0) /* XXX repeat too much code. */ for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) { register char *lp; register char *rp; register int c; lp = name; rp = (*aux_cmdp)->name; while ((c = *lp) == *rp) { if (c == 0) { /* complete match */ *cmdp = *aux_cmdp; return (CMD_UNIQUE); } lp++; rp++; } if (c == 0) { /* end of name, not end of command - partial match */ if (result == CMD_FOUND) { result = CMD_AMBIGUOUS; /* but keep looking for a full match - this lets us match single letters */ } else { *cmdp = *aux_cmdp; result = CMD_FOUND; } } } if (result == CMD_NONE) { /* check for 'help' */ if (name[0] == 'h' && name[1] == 'e' && name[2] == 'l' && name[3] == 'p') result = CMD_HELP; } return (result); } static void db_cmd_list(table, aux_tablep, aux_tablep_end) struct command *table; struct command **aux_tablep; struct command **aux_tablep_end; { register struct command *cmd; register struct command **aux_cmdp; for (cmd = table; cmd->name != 0; cmd++) { db_printf("%-12s", cmd->name); db_end_line(); } if (aux_tablep == 0) return; for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) { db_printf("%-12s", (*aux_cmdp)->name); db_end_line(); } } static void db_command(last_cmdp, cmd_table, aux_cmd_tablep, aux_cmd_tablep_end) struct command **last_cmdp; /* IN_OUT */ struct command *cmd_table; struct command **aux_cmd_tablep; struct command **aux_cmd_tablep_end; { struct command *cmd; int t; char modif[TOK_STRING_SIZE]; db_expr_t addr, count; boolean_t have_addr = FALSE; int result; t = db_read_token(); if (t == tEOL) { /* empty line repeats last command, at 'next' */ cmd = *last_cmdp; addr = (db_expr_t)db_next; have_addr = FALSE; count = 1; modif[0] = '\0'; } else if (t == tEXCL) { db_fncall((db_expr_t)0, (boolean_t)0, (db_expr_t)0, (char *)0); return; } else if (t != tIDENT) { db_printf("?\n"); db_flush_lex(); return; } else { /* * Search for command */ while (cmd_table) { result = db_cmd_search(db_tok_string, cmd_table, aux_cmd_tablep, aux_cmd_tablep_end, &cmd); switch (result) { case CMD_NONE: db_printf("No such command\n"); db_flush_lex(); return; case CMD_AMBIGUOUS: db_printf("Ambiguous\n"); db_flush_lex(); return; case CMD_HELP: db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end); db_flush_lex(); return; default: break; } if ((cmd_table = cmd->more) != 0) { /* XXX usually no more aux's. */ aux_cmd_tablep = 0; if (cmd_table == db_show_cmds) { aux_cmd_tablep = SET_BEGIN(db_show_cmd_set); aux_cmd_tablep_end = SET_LIMIT(db_show_cmd_set); } t = db_read_token(); if (t != tIDENT) { db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end); db_flush_lex(); return; } } } if ((cmd->flag & CS_OWN) == 0) { /* * Standard syntax: * command [/modifier] [addr] [,count] */ t = db_read_token(); if (t == tSLASH) { t = db_read_token(); if (t != tIDENT) { db_printf("Bad modifier\n"); db_flush_lex(); return; } db_strcpy(modif, db_tok_string); } else { db_unread_token(t); modif[0] = '\0'; } if (db_expression(&addr)) { db_dot = (db_addr_t) addr; db_last_addr = db_dot; have_addr = TRUE; } else { addr = (db_expr_t) db_dot; have_addr = FALSE; } t = db_read_token(); if (t == tCOMMA) { if (!db_expression(&count)) { db_printf("Count missing\n"); db_flush_lex(); return; } } else { db_unread_token(t); count = -1; } if ((cmd->flag & CS_MORE) == 0) { db_skip_to_eol(); } } } *last_cmdp = cmd; if (cmd != 0) { /* * Execute the command. */ (*cmd->fcn)(addr, have_addr, count, modif); db_setup_paging(NULL, NULL, -1); if (cmd->flag & CS_SET_DOT) { /* * If command changes dot, set dot to * previous address displayed (if 'ed' style). */ if (db_ed_style) { db_dot = db_prev; } else { db_dot = db_next; } } else { /* * If command does not change dot, * set 'next' location to be the same. */ db_next = db_dot; } } } /* * 'show' commands */ static struct command db_show_all_cmds[] = { -#if 0 - { "threads", db_show_all_threads, 0, 0 }, -#endif { "procs", db_ps, 0, 0 }, { (char *)0 } }; static struct command db_show_cmds[] = { { "all", 0, 0, db_show_all_cmds }, { "registers", db_show_regs, 0, 0 }, { "breaks", db_listbreak_cmd, 0, 0 }, - { "thread", db_show_one_thread, 0, 0 }, -#if 0 - { "port", ipc_port_print, 0, 0 }, -#endif + { "threads", db_show_threads, 0, 0 }, { (char *)0, } }; static struct command db_command_table[] = { { "print", db_print_cmd, 0, 0 }, { "p", db_print_cmd, 0, 0 }, { "examine", db_examine_cmd, CS_SET_DOT, 0 }, { "x", db_examine_cmd, CS_SET_DOT, 0 }, { "search", db_search_cmd, CS_OWN|CS_SET_DOT, 0 }, { "set", db_set_cmd, CS_OWN, 0 }, { "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, { "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, { "delete", db_delete_cmd, 0, 0 }, { "d", db_delete_cmd, 0, 0 }, { "break", db_breakpoint_cmd, 0, 0 }, { "dwatch", db_deletewatch_cmd, 0, 0 }, { "watch", db_watchpoint_cmd, CS_MORE,0 }, { "dhwatch", db_deletehwatch_cmd, 0, 0 }, { "hwatch", db_hwatchpoint_cmd, 0, 0 }, { "step", db_single_step_cmd, 0, 0 }, { "s", db_single_step_cmd, 0, 0 }, { "continue", db_continue_cmd, 0, 0 }, { "c", db_continue_cmd, 0, 0 }, { "until", db_trace_until_call_cmd,0, 0 }, { "next", db_trace_until_matching_cmd,0, 0 }, { "match", db_trace_until_matching_cmd,0, 0 }, { "trace", db_stack_trace_cmd, 0, 0 }, { "where", db_stack_trace_cmd, 0, 0 }, { "call", db_fncall, CS_OWN, 0 }, { "show", 0, 0, db_show_cmds }, { "ps", db_ps, 0, 0 }, - { "gdb", db_gdb, 0, 0 }, { "reset", db_reset, 0, 0 }, { "kill", db_kill, CS_OWN, 0 }, { "watchdog", db_watchdog, 0, 0 }, + { "thread", db_set_thread, CS_OWN, 0 }, { (char *)0, } }; static struct command *db_last_command = 0; -#if 0 -void -db_help_cmd() -{ - struct command *cmd = db_command_table; - - while (cmd->name != 0) { - db_printf("%-12s", cmd->name); - db_end_line(); - cmd++; - } -} -#endif - /* * At least one non-optional command must be implemented using * DB_COMMAND() so that db_cmd_set gets created. Here is one. */ DB_COMMAND(panic, db_panic) { panic("from debugger"); } void db_command_loop() { /* * Initialize 'prev' and 'next' to dot. */ db_prev = db_dot; db_next = db_dot; db_cmd_loop_done = 0; while (!db_cmd_loop_done) { - - (void) setjmp(db_jmpbuf); if (db_print_position() != 0) db_printf("\n"); db_printf("db> "); (void) db_read_line(); db_command(&db_last_command, db_command_table, SET_BEGIN(db_cmd_set), SET_LIMIT(db_cmd_set)); } } void db_error(s) const char *s; { if (s) db_printf("%s", s); db_flush_lex(); - longjmp(db_jmpbuf, 1); + kdb_reenter(); } /* * Call random function: * !expr(arg,arg,arg) */ static void db_fncall(dummy1, dummy2, dummy3, dummy4) db_expr_t dummy1; boolean_t dummy2; db_expr_t dummy3; char * dummy4; { db_expr_t fn_addr; #define MAXARGS 11 /* XXX only 10 are passed */ db_expr_t args[MAXARGS]; int nargs = 0; db_expr_t retval; typedef db_expr_t fcn_10args_t(db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t); fcn_10args_t *func; int t; if (!db_expression(&fn_addr)) { db_printf("Bad function\n"); db_flush_lex(); return; } func = (fcn_10args_t *)fn_addr; /* XXX */ t = db_read_token(); if (t == tLPAREN) { if (db_expression(&args[0])) { nargs++; while ((t = db_read_token()) == tCOMMA) { if (nargs == MAXARGS) { db_printf("Too many arguments\n"); db_flush_lex(); return; } if (!db_expression(&args[nargs])) { db_printf("Argument missing\n"); db_flush_lex(); return; } nargs++; } db_unread_token(t); } if (db_read_token() != tRPAREN) { db_printf("?\n"); db_flush_lex(); return; } } db_skip_to_eol(); while (nargs < MAXARGS) { args[nargs++] = 0; } retval = (*func)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9] ); db_printf("%#lr\n", (long)retval); -} - -/* Enter GDB remote protocol debugger on the next trap. */ - -void *gdb_arg = NULL; -cn_getc_t *gdb_getc; -cn_putc_t *gdb_putc; - -static void -db_gdb (dummy1, dummy2, dummy3, dummy4) - db_expr_t dummy1; - boolean_t dummy2; - db_expr_t dummy3; - char * dummy4; -{ - - if (gdb_arg == NULL) { - db_printf("No gdb port enabled. Set flag 0x80 on desired port\n"); - db_printf("in your configuration file (currently sio only).\n"); - return; - } - boothowto ^= RB_GDB; - - db_printf("Next trap will enter %s\n", - boothowto & RB_GDB ? "GDB remote protocol mode" - : "DDB debugger"); } static void db_kill(dummy1, dummy2, dummy3, dummy4) db_expr_t dummy1; boolean_t dummy2; db_expr_t dummy3; char * dummy4; { db_expr_t old_radix, pid, sig; struct proc *p; #define DB_ERROR(f) do { db_printf f; db_flush_lex(); goto out; } while (0) /* * PIDs and signal numbers are typically represented in base * 10, so make that the default here. It can, of course, be * overridden by specifying a prefix. */ old_radix = db_radix; db_radix = 10; /* Retrieve arguments. */ if (!db_expression(&sig)) DB_ERROR(("Missing signal number\n")); if (!db_expression(&pid)) DB_ERROR(("Missing process ID\n")); db_skip_to_eol(); if (sig < 0 || sig > _SIG_MAXSIG) DB_ERROR(("Signal number out of range\n")); /* * Find the process in question. allproc_lock is not needed * since we're in DDB. */ /* sx_slock(&allproc_lock); */ LIST_FOREACH(p, &allproc, p_list) if (p->p_pid == pid) break; /* sx_sunlock(&allproc_lock); */ if (p == NULL) DB_ERROR(("Can't find process with pid %ld\n", (long) pid)); /* If it's already locked, bail; otherwise, do the deed. */ if (PROC_TRYLOCK(p) == 0) DB_ERROR(("Can't lock process with pid %ld\n", (long) pid)); else { psignal(p, sig); PROC_UNLOCK(p); } out: db_radix = old_radix; #undef DB_ERROR } static void db_reset(dummy1, dummy2, dummy3, dummy4) db_expr_t dummy1; boolean_t dummy2; db_expr_t dummy3; char * dummy4; { cpu_reset(); } static void db_watchdog(dummy1, dummy2, dummy3, dummy4) db_expr_t dummy1; boolean_t dummy2; db_expr_t dummy3; char * dummy4; { int i; /* * XXX: It might make sense to be able to set the watchdog to a * XXX: timeout here so that failure or hang as a result of subsequent * XXX: ddb commands could be recovered by a reset. */ EVENTHANDLER_INVOKE(watchdog_list, 0, &i); } Index: head/sys/ddb/db_main.c =================================================================== --- head/sys/ddb/db_main.c (nonexistent) +++ head/sys/ddb/db_main.c (revision 131952) @@ -0,0 +1,226 @@ +/* + * Mach Operating System + * Copyright (c) 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 + * 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 the + * rights to redistribute these changes. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +static dbbe_init_f db_init; +static dbbe_trap_f db_trap; + +KDB_BACKEND(ddb, db_init, db_trace_self, db_trap); + +vm_offset_t ksym_start, ksym_end; + +boolean_t +X_db_line_at_pc(db_symtab_t *symtab, c_db_sym_t sym, char **file, int *line, + db_expr_t off) +{ + return (FALSE); +} + +c_db_sym_t +X_db_lookup(db_symtab_t *symtab, const char *symbol) +{ + c_linker_sym_t lsym; + Elf_Sym *sym; + + if (symtab->private == NULL) { + return ((c_db_sym_t)((!linker_ddb_lookup(symbol, &lsym)) + ? lsym : NULL)); + } else { + sym = (Elf_Sym *)symtab->start; + while ((char *)sym < symtab->end) { + if (sym->st_name != 0 && + !strcmp(symtab->private + sym->st_name, symbol)) + return ((c_db_sym_t)sym); + sym++; + } + } + return (NULL); +} + +c_db_sym_t +X_db_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strat, + db_expr_t *diffp) +{ + c_linker_sym_t lsym; + Elf_Sym *sym, *match; + unsigned long diff; + + if (symtab->private == NULL) { + if (!linker_ddb_search_symbol((caddr_t)off, &lsym, &diff)) { + *diffp = (db_expr_t)diff; + return ((c_db_sym_t)lsym); + } + return (NULL); + } + + diff = ~0UL; + match = NULL; + for (sym = (Elf_Sym*)symtab->start; (char*)sym < symtab->end; sym++) { + if (sym->st_name == 0) + continue; + if (off < sym->st_value) + continue; + if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT && + ELF_ST_TYPE(sym->st_info) != STT_FUNC && + ELF_ST_TYPE(sym->st_info) != STT_NOTYPE) + continue; + if ((off - sym->st_value) > diff) + continue; + if ((off - sym->st_value) < diff) { + diff = off - sym->st_value; + match = sym; + } else { + if (match == NULL) + match = sym; + else if (ELF_ST_BIND(match->st_info) == STB_LOCAL && + ELF_ST_BIND(sym->st_info) != STB_LOCAL) + match = sym; + } + if (diff == 0) { + if (strat == DB_STGY_PROC && + ELF_ST_TYPE(sym->st_info) == STT_FUNC && + ELF_ST_BIND(sym->st_info) != STB_LOCAL) + break; + if (strat == DB_STGY_ANY && + ELF_ST_BIND(sym->st_info) != STB_LOCAL) + break; + } + } + + *diffp = (match == NULL) ? off : diff; + return ((c_db_sym_t)match); +} + +boolean_t +X_db_sym_numargs(db_symtab_t *symtab, c_db_sym_t sym, int *nargp, + char **argp) +{ + return (FALSE); +} + +void +X_db_symbol_values(db_symtab_t *symtab, c_db_sym_t sym, const char **namep, + db_expr_t *valp) +{ + linker_symval_t lval; + + if (symtab->private == NULL) { + linker_ddb_symbol_values((c_linker_sym_t)sym, &lval); + if (namep != NULL) + *namep = (const char*)lval.name; + if (valp != NULL) + *valp = (db_expr_t)lval.value; + } else { + if (namep != NULL) + *namep = (const char *)symtab->private + + ((const Elf_Sym *)sym)->st_name; + if (valp != NULL) + *valp = (db_expr_t)((const Elf_Sym *)sym)->st_value; + } +} + +static int +db_init(void) +{ + uintptr_t symtab, strtab; + Elf_Size tabsz, strsz; + + if (ksym_end > ksym_start && ksym_start != 0) { + symtab = ksym_start; + tabsz = *((Elf_Size*)symtab)++; + strtab = symtab + tabsz; + strsz = *((Elf_Size*)strtab)++; + if (strtab + strsz <= ksym_end) { + db_add_symbol_table((char *)symtab, + (char *)(symtab + tabsz), "elf", (char *)strtab); + } + } + db_add_symbol_table(NULL, NULL, "kld", NULL); + return (1); /* We're the default debugger. */ +} + +static int +db_trap(int type, int code) +{ + jmp_buf jb; + void *prev_jb; + boolean_t bkpt, watchpt; + + /* + * Don't handle the trap if the console is unavailable (i.e. it + * is in graphics mode). + */ + if (cnunavailable()) + return (0); + + bkpt = IS_BREAKPOINT_TRAP(type, code); + watchpt = IS_WATCHPOINT_TRAP(type, code); + + if (db_stop_at_pc(&bkpt)) { + if (db_inst_count) { + db_printf("After %d instructions (%d loads, %d stores),\n", + db_inst_count, db_load_count, db_store_count); + } + prev_jb = kdb_jmpbuf(jb); + if (setjmp(jb) == 0) { + db_dot = PC_REGS(); + db_print_thread(); + if (bkpt) + db_printf("Breakpoint at\t"); + else if (watchpt) + db_printf("Watchpoint at\t"); + else + db_printf("Stopped at\t"); + db_print_loc_and_inst(db_dot); + } + db_command_loop(); + (void)kdb_jmpbuf(prev_jb); + } + + db_restart_at_pc(watchpt); + + return (1); +} Property changes on: head/sys/ddb/db_main.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/ddb/db_output.c =================================================================== --- head/sys/ddb/db_output.c (revision 131951) +++ head/sys/ddb/db_output.c (revision 131952) @@ -1,290 +1,291 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. */ /* * Author: David B. Golub, Carnegie Mellon University * Date: 7/90 */ /* * Printf and character output for debugger. */ #include __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include #include #include /* * Character output - tracks position in line. * To do this correctly, we should know how wide * the output device is - then we could zero * the line position when the output device wraps * around to the start of the next line. * * Instead, we count the number of spaces printed * since the last printing character so that we * don't print trailing spaces. This avoids most * of the wraparounds. */ static int db_output_position = 0; /* output column */ static int db_last_non_space = 0; /* last non-space character */ db_expr_t db_tab_stop_width = 8; /* how wide are tab stops? */ #define NEXT_TAB(i) \ ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width) db_expr_t db_max_width = 79; /* output line width */ static int db_newlines; /* # lines this page */ static int db_maxlines = -1; /* max lines per page */ static db_page_calloutfcn_t *db_page_callout = NULL; static void *db_page_callout_arg = NULL; static int ddb_use_printf = 0; SYSCTL_INT(_debug, OID_AUTO, ddb_use_printf, CTLFLAG_RW, &ddb_use_printf, 0, "use printf for all ddb output"); static void db_putchar(int c, void *arg); /* * Force pending whitespace. */ void db_force_whitespace() { register int last_print, next_tab; last_print = db_last_non_space; while (last_print < db_output_position) { next_tab = NEXT_TAB(last_print); if (next_tab <= db_output_position) { while (last_print < next_tab) { /* DON'T send a tab!!! */ cnputc(' '); last_print++; } } else { cnputc(' '); last_print++; } } db_last_non_space = db_output_position; } /* * Output character. Buffer whitespace. */ static void db_putchar(c, arg) int c; /* character to output */ void * arg; { /* * If not in the debugger or the user requests it, output data to * both the console and the message buffer. */ - if (!db_active || ddb_use_printf) { + if (!kdb_active || ddb_use_printf) { printf("%c", c); - if (!db_active) + if (!kdb_active) return; if (c == '\r' || c == '\n') db_check_interrupt(); if (c == '\n' && db_maxlines > 0 && db_page_callout != NULL) { db_newlines++; if (db_newlines >= db_maxlines) { db_maxlines = -1; db_page_callout(db_page_callout_arg); } } return; } /* Otherwise, output data directly to the console. */ if (c > ' ' && c <= '~') { /* * Printing character. * If we have spaces to print, print them first. * Use tabs if possible. */ db_force_whitespace(); cnputc(c); db_output_position++; db_last_non_space = db_output_position; } else if (c == '\n') { /* Newline */ cnputc(c); db_output_position = 0; db_last_non_space = 0; db_check_interrupt(); if (db_maxlines > 0 && db_page_callout != NULL) { db_newlines++; if (db_newlines >= db_maxlines) { db_maxlines = -1; db_page_callout(db_page_callout_arg); } } } else if (c == '\r') { /* Return */ cnputc(c); db_output_position = 0; db_last_non_space = 0; db_check_interrupt(); } else if (c == '\t') { /* assume tabs every 8 positions */ db_output_position = NEXT_TAB(db_output_position); } else if (c == ' ') { /* space */ db_output_position++; } else if (c == '\007') { /* bell */ cnputc(c); } /* other characters are assumed non-printing */ } /* * Register callout for providing a pager for output. */ void db_setup_paging(db_page_calloutfcn_t *callout, void *arg, int maxlines) { db_page_callout = callout; db_page_callout_arg = arg; db_maxlines = maxlines; db_newlines = 0; } /* * A simple paging callout function. If the argument is not null, it * points to an integer that will be set to 1 if the user asks to quit. */ void db_simple_pager(void *arg) { int c; db_printf("--More--\r"); for (;;) { c = cngetc(); switch (c) { case '\n': /* Just one more line. */ db_setup_paging(db_simple_pager, arg, 1); return; case ' ': /* Another page. */ db_setup_paging(db_simple_pager, arg, DB_LINES_PER_PAGE); return; case 'q': case 'Q': case 'x': case 'X': /* Quit */ if (arg != NULL) { *(int *)arg = 1; db_printf("\n"); return; } #if 0 /* FALLTHROUGH */ default: cnputc('\007'); #endif } } } /* * Return output position */ int db_print_position() { return (db_output_position); } /* * Printing */ void #if __STDC__ db_printf(const char *fmt, ...) #else db_printf(fmt) const char *fmt; #endif { va_list listp; va_start(listp, fmt); kvprintf (fmt, db_putchar, NULL, db_radix, listp); va_end(listp); } int db_indent; void #if __STDC__ db_iprintf(const char *fmt,...) #else db_iprintf(fmt) const char *fmt; #endif { register int i; va_list listp; for (i = db_indent; i >= 8; i -= 8) db_printf("\t"); while (--i >= 0) db_printf(" "); va_start(listp, fmt); kvprintf (fmt, db_putchar, NULL, db_radix, listp); va_end(listp); } /* * End line if too long. */ void db_end_line() { if (db_output_position >= db_max_width) db_printf("\n"); } Index: head/sys/ddb/db_print.c =================================================================== --- head/sys/ddb/db_print.c (revision 131951) +++ head/sys/ddb/db_print.c (revision 131952) @@ -1,69 +1,69 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. * */ /* * Author: David B. Golub, Carnegie Mellon University * Date: 7/90 */ /* * Miscellaneous printing. */ #include __FBSDID("$FreeBSD$"); #include +#include +#include + #include #include #include void -db_show_regs(dummy1, dummy2, dummy3, dummy4) - db_expr_t dummy1; - boolean_t dummy2; - db_expr_t dummy3; - char * dummy4; +db_show_regs(db_expr_t _1, boolean_t _2, db_expr_t _3, char *_4) { - register struct db_variable *regp; - db_expr_t value, offset; - const char * name; + struct db_variable *regp; + db_expr_t value, offset; + const char *name; for (regp = db_regs; regp < db_eregs; regp++) { - db_read_variable(regp, &value); - db_printf("%-12s%#10lr", regp->name, (unsigned long)value); - db_find_xtrn_sym_and_offset((db_addr_t)value, &name, &offset); - if (name != NULL && offset <= (unsigned long)db_maxoff && - offset != value) { - db_printf("\t%s", name); - if (offset != 0) - db_printf("+%+#lr", (long)offset); - } - db_printf("\n"); + if (!db_read_variable(regp, &value)) + continue; + db_printf("%-12s%#10lr", regp->name, (unsigned long)value); + db_find_xtrn_sym_and_offset((db_addr_t)value, &name, &offset); + if (name != NULL && offset <= (unsigned long)db_maxoff && + offset != value) { + db_printf("\t%s", name); + if (offset != 0) + db_printf("+%+#lr", (long)offset); + } + db_printf("\n"); } - db_print_loc_and_inst(PC_REGS(DDB_REGS)); + db_print_loc_and_inst(PC_REGS()); } Index: head/sys/ddb/db_ps.c =================================================================== --- head/sys/ddb/db_ps.c (revision 131951) +++ head/sys/ddb/db_ps.c (revision 131952) @@ -1,194 +1,168 @@ /*- * Copyright (c) 1993 The Regents of the University of California. * 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. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include static void dumpthread(volatile struct proc *p, volatile struct thread *td); void db_ps(dummy1, dummy2, dummy3, dummy4) db_expr_t dummy1; boolean_t dummy2; db_expr_t dummy3; char * dummy4; { volatile struct proc *p, *pp; volatile struct thread *td; char *state; int np, quit; np = nprocs; quit = 0; /* sx_slock(&allproc_lock); */ if (!LIST_EMPTY(&allproc)) p = LIST_FIRST(&allproc); else p = &proc0; db_setup_paging(db_simple_pager, &quit, DB_LINES_PER_PAGE); db_printf(" pid proc uarea uid ppid pgrp flag stat wmesg wchan cmd\n"); while (--np >= 0 && !quit) { if (p == NULL) { printf("oops, ran out of processes early!\n"); break; } /* PROC_LOCK(p); */ pp = p->p_pptr; if (pp == NULL) pp = p; switch(p->p_state) { case PRS_NORMAL: if (P_SHOULDSTOP(p)) state = "stop"; else state = ""; break; case PRS_NEW: state = "new "; break; case PRS_ZOMBIE: state = "zomb"; break; default: state = "Unkn"; break; } db_printf("%5d %8p %8p %4d %5d %5d %07x %s", p->p_pid, (volatile void *)p, (void *)p->p_uarea, p->p_ucred != NULL ? p->p_ucred->cr_ruid : 0, pp->p_pid, p->p_pgrp != NULL ? p->p_pgrp->pg_id : 0, p->p_flag, state); if (p->p_flag & P_SA) db_printf("(threaded) %s\n", p->p_comm); FOREACH_THREAD_IN_PROC(p, td) { dumpthread(p, td); if (quit) break; } /* PROC_UNLOCK(p); */ p = LIST_NEXT(p, p_list); if (p == NULL && np > 0) p = LIST_FIRST(&zombproc); } /* sx_sunlock(&allproc_lock); */ } static void dumpthread(volatile struct proc *p, volatile struct thread *td) { if (p->p_flag & P_SA) db_printf( " thread %p ksegrp %p ", td, td->td_ksegrp); if (TD_ON_SLEEPQ(td)) db_printf("[SLPQ %s %p]", td->td_wmesg, (void *)td->td_wchan); switch (td->td_state) { case TDS_INHIBITED: if (TD_ON_LOCK(td)) { db_printf("[LOCK %6s %8p]", td->td_lockname, (void *)td->td_blocked); } if (TD_IS_SLEEPING(td)) { db_printf("[SLP]"); } if (TD_IS_SWAPPED(td)) { db_printf("[SWAP]"); } if (TD_IS_SUSPENDED(td)) { db_printf("[SUSP]"); } if (TD_AWAITING_INTR(td)) { db_printf("[IWAIT]"); } break; case TDS_CAN_RUN: db_printf("[Can run]"); break; case TDS_RUNQ: db_printf("[RUNQ]"); break; case TDS_RUNNING: db_printf("[CPU %d]", td->td_oncpu); break; case TDS_INACTIVE: db_printf("[INACTIVE]"); break; default: db_printf("[UNK: %#x]", td->td_state); } if (p->p_flag & P_SA) { if (td->td_kse) db_printf("[kse %p]", td->td_kse); db_printf("\n"); } else db_printf(" %s\n", p->p_comm); } - - -#define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK) -void -db_show_one_thread(db_expr_t addr, boolean_t have_addr, - db_expr_t count, char *modif) -{ - struct proc *p; - struct thread *td; - - if (!have_addr) - td = curthread; - else if (!INKERNEL(addr)) { - printf("bad thread address"); - return; - } else - td = (struct thread *)addr; - /* quick sanity check */ - if ((p = td->td_proc) != td->td_ksegrp->kg_proc) - return; - printf("Proc %p ",p); - dumpthread(p, td); -#ifdef __i386__ - db_stack_thread((db_expr_t)td, 1, count, modif); -#endif -} Index: head/sys/ddb/db_run.c =================================================================== --- head/sys/ddb/db_run.c (revision 131951) +++ head/sys/ddb/db_run.c (revision 131952) @@ -1,396 +1,382 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. */ /* * Author: David B. Golub, Carnegie Mellon University * Date: 7/90 */ /* * Commands to run process. */ #include __FBSDID("$FreeBSD$"); #include +#include +#include +#include + #include #include #include #include static 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 static boolean_t db_sstep_print; static int db_loop_count; static int db_call_depth; int db_inst_count; int db_load_count; int db_store_count; #ifndef db_set_single_step -extern void db_set_single_step(db_regs_t *regs); +void db_set_single_step(void); #endif #ifndef db_clear_single_step -extern void db_clear_single_step(db_regs_t *regs); +void db_clear_single_step(void); #endif -#ifdef notused -static void db_single_step(db_regs_t *regs); -#endif - boolean_t db_stop_at_pc(is_breakpoint) boolean_t *is_breakpoint; { register db_addr_t pc; register db_breakpoint_t bkpt; - db_clear_single_step(DDB_REGS); + db_clear_single_step(); db_clear_breakpoints(); db_clear_watchpoints(); - pc = PC_REGS(DDB_REGS); + pc = PC_REGS(); #ifdef FIXUP_PC_AFTER_BREAK if (*is_breakpoint) { /* * Breakpoint trap. Fix up the PC if the * machine requires it. */ FIXUP_PC_AFTER_BREAK - pc = PC_REGS(DDB_REGS); + pc = PC_REGS(); } #endif /* * Now check for a breakpoint at this address. */ bkpt = db_find_breakpoint_here(pc); if (bkpt) { if (--bkpt->count == 0) { bkpt->count = bkpt->init_count; *is_breakpoint = TRUE; return (TRUE); /* stop here */ } } else if (*is_breakpoint) { #ifdef BKPT_SKIP BKPT_SKIP; #endif } *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) { /* continue until matching return */ db_expr_t ins; ins = db_get_value(pc, sizeof(int), FALSE); if (!inst_trap_return(ins) && (!inst_return(ins) || --db_call_depth != 0)) { if (db_sstep_print) { if (inst_call(ins) || inst_return(ins)) { register 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) { /* continue until call or return */ db_expr_t ins; ins = db_get_value(pc, sizeof(int), FALSE); 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(watchpt) boolean_t watchpt; { - register db_addr_t pc = PC_REGS(DDB_REGS); + register db_addr_t pc = PC_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++; db_load_count += inst_load(ins); db_store_count += inst_store(ins); #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++; db_load_count += inst_load(ins); db_store_count += inst_store(ins); } #endif /* SOFTWARE_SSTEP */ } if (db_run_mode == STEP_CONTINUE) { if (watchpt || db_find_breakpoint_here(pc)) { /* * Step over breakpoint/watchpoint. */ db_run_mode = STEP_INVISIBLE; - db_set_single_step(DDB_REGS); + db_set_single_step(); } else { db_set_breakpoints(); db_set_watchpoints(); } } else { - db_set_single_step(DDB_REGS); + db_set_single_step(); } } -#ifdef notused -static void -db_single_step(regs) - db_regs_t *regs; -{ - if (db_run_mode == STEP_CONTINUE) { - db_run_mode = STEP_INVISIBLE; - db_set_single_step(regs); - } -} -#endif - #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(), returns true if the instruction might branch * extern unsigned * branch_taken(), return the address the instruction might * branch to * db_getreg_val(); 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. */ db_breakpoint_t db_not_taken_bkpt = 0; db_breakpoint_t db_taken_bkpt = 0; void -db_set_single_step(regs) - register db_regs_t *regs; +db_set_single_step(void) { - db_addr_t pc = PC_REGS(regs), brpc; - unsigned inst; + db_addr_t pc = PC_REGS(), brpc; + unsigned 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)) { - brpc = branch_taken(inst, pc, regs); - if (brpc != pc) { /* self-branches are hopeless */ - db_taken_bkpt = db_set_temp_breakpoint(brpc); - } - pc = next_instr_address(pc,1); + brpc = branch_taken(inst, pc); + if (brpc != pc) { /* self-branches are hopeless */ + db_taken_bkpt = db_set_temp_breakpoint(brpc); + } + pc = next_instr_address(pc, 1); } - pc = next_instr_address(pc,0); + pc = next_instr_address(pc, 0); db_not_taken_bkpt = db_set_temp_breakpoint(pc); } void -db_clear_single_step(regs) - db_regs_t *regs; +db_clear_single_step(void) { if (db_not_taken_bkpt != 0) { - db_delete_temp_breakpoint(db_not_taken_bkpt); - db_not_taken_bkpt = 0; + db_delete_temp_breakpoint(db_not_taken_bkpt); + db_not_taken_bkpt = 0; } if (db_taken_bkpt != 0) { - db_delete_temp_breakpoint(db_taken_bkpt); - db_taken_bkpt = 0; + db_delete_temp_breakpoint(db_taken_bkpt); + db_taken_bkpt = 0; } } #endif /* SOFTWARE_SSTEP */ extern int db_cmd_loop_done; /* single-step */ /*ARGSUSED*/ void db_single_step_cmd(addr, have_addr, count, modif) db_expr_t addr; boolean_t 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_load_count = 0; db_store_count = 0; db_cmd_loop_done = 1; } /* trace and print until call/return */ /*ARGSUSED*/ void db_trace_until_call_cmd(addr, have_addr, count, modif) db_expr_t addr; boolean_t 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_load_count = 0; db_store_count = 0; db_cmd_loop_done = 1; } /*ARGSUSED*/ void db_trace_until_matching_cmd(addr, have_addr, count, modif) db_expr_t addr; boolean_t 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_load_count = 0; db_store_count = 0; db_cmd_loop_done = 1; } /* continue */ /*ARGSUSED*/ void db_continue_cmd(addr, have_addr, count, modif) db_expr_t addr; boolean_t 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_load_count = 0; db_store_count = 0; db_cmd_loop_done = 1; } Index: head/sys/ddb/db_thread.c =================================================================== --- head/sys/ddb/db_thread.c (nonexistent) +++ head/sys/ddb/db_thread.c (revision 131952) @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include + +#include +#include +#include + +void +db_print_thread(void) +{ + db_printf("[thread %ld]\n", (long)kdb_thread->td_tid); +} + +void +db_set_thread(db_expr_t tid, boolean_t hastid, db_expr_t cnt, char *mod) +{ + struct thread *thr; + db_expr_t radix; + int err; + + /* + * We parse our own arguments. We don't like the default radix. + */ + radix = db_radix; + db_radix = 10; + hastid = db_expression(&tid); + db_radix = radix; + db_skip_to_eol(); + + if (hastid) { + thr = kdb_thr_lookup(tid); + if (thr != NULL) { + err = kdb_thr_select(thr); + if (err != 0) { + db_printf("unable to switch to thread %ld\n", + (long)thr->td_tid); + return; + } + db_dot = PC_REGS(); + } else { + db_printf("%d: invalid thread\n", (int)tid); + return; + } + } + + db_print_thread(); + db_print_loc_and_inst(PC_REGS()); +} + +void +db_show_threads(db_expr_t addr, boolean_t hasaddr, db_expr_t cnt, char *mod) +{ + jmp_buf jb; + void *prev_jb; + struct thread *thr; + int pager_quit; + + db_setup_paging(db_simple_pager, &pager_quit, DB_LINES_PER_PAGE); + + pager_quit = 0; + thr = kdb_thr_first(); + while (!pager_quit && thr != NULL) { + db_printf(" %6ld (%p) ", (long)thr->td_tid, thr); + prev_jb = kdb_jmpbuf(jb); + if (setjmp(jb) == 0) { + if (db_trace_thread(thr, 1) != 0) + db_printf("***\n"); + } + kdb_jmpbuf(prev_jb); + thr = kdb_thr_next(thr); + } +} Property changes on: head/sys/ddb/db_thread.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/ddb/db_variables.c =================================================================== --- head/sys/ddb/db_variables.c (revision 131951) +++ head/sys/ddb/db_variables.c (revision 131952) @@ -1,173 +1,152 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. */ /* * Author: David B. Golub, Carnegie Mellon University * Date: 7/90 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include static int db_find_variable(struct db_variable **varp); -static void db_write_variable(struct db_variable *, db_expr_t *); -#ifdef notused -static int db_set_variable(db_expr_t value); -#endif - static struct db_variable db_vars[] = { { "radix", &db_radix, FCN_NULL }, { "maxoff", &db_maxoff, FCN_NULL }, { "maxwidth", &db_max_width, FCN_NULL }, { "tabstops", &db_tab_stop_width, FCN_NULL }, }; -static struct db_variable *db_evars = - db_vars + sizeof(db_vars)/sizeof(db_vars[0]); +static struct db_variable *db_evars = + db_vars + sizeof(db_vars)/sizeof(db_vars[0]); static int -db_find_variable(varp) - struct db_variable **varp; +db_find_variable(struct db_variable **varp) { - int t; struct db_variable *vp; + int t; 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_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); + for (vp = db_regs; vp < db_eregs; vp++) { + if (!strcmp(db_tok_string, vp->name)) { + *varp = vp; + return (1); + } } - } } db_error("Unknown variable\n"); return (0); } int -db_get_variable(valuep) - db_expr_t *valuep; +db_get_variable(db_expr_t *valuep) { struct db_variable *vp; if (!db_find_variable(&vp)) - return (0); + return (0); - db_read_variable(vp, valuep); - - return (1); + return (db_read_variable(vp, valuep)); } -#ifdef notused -static int -db_set_variable(value) - db_expr_t value; +int +db_set_variable(db_expr_t value) { struct db_variable *vp; if (!db_find_variable(&vp)) - return (0); + return (0); - db_write_variable(vp, &value); - - return (1); + return (db_write_variable(vp, value)); } -#endif -void -db_read_variable(vp, valuep) - struct db_variable *vp; - db_expr_t *valuep; +int +db_read_variable(struct db_variable *vp, db_expr_t *valuep) { - db_varfcn_t *func = vp->fcn; + db_varfcn_t *func = vp->fcn; - if (func == FCN_NULL) - *valuep = *(vp->valuep); - else - (*func)(vp, valuep, DB_VAR_GET); + if (func == FCN_NULL) { + *valuep = *(vp->valuep); + return (1); + } + return ((*func)(vp, valuep, DB_VAR_GET)); } -static void -db_write_variable(vp, valuep) - struct db_variable *vp; - db_expr_t *valuep; +int +db_write_variable(struct db_variable *vp, db_expr_t value) { - db_varfcn_t *func = vp->fcn; + db_varfcn_t *func = vp->fcn; - if (func == FCN_NULL) - *(vp->valuep) = *valuep; - else - (*func)(vp, valuep, DB_VAR_SET); + if (func == FCN_NULL) { + *(vp->valuep) = value; + return (1); + } + return ((*func)(vp, &value, DB_VAR_SET)); } void -db_set_cmd(dummy1, dummy2, dummy3, dummy4) - db_expr_t dummy1; - boolean_t dummy2; - db_expr_t dummy3; - char * dummy4; +db_set_cmd(db_expr_t dummy1, boolean_t dummy2, db_expr_t dummy3, char *dummy4) { - db_expr_t value; struct db_variable *vp; - int t; + db_expr_t value; + int t; t = db_read_token(); if (t != tDOLLAR) { - db_error("Unknown variable\n"); - return; + db_error("Unknown variable\n"); + return; } if (!db_find_variable(&vp)) { - db_error("Unknown variable\n"); - return; + db_error("Unknown variable\n"); + return; } t = db_read_token(); if (t != tEQ) - db_unread_token(t); + db_unread_token(t); if (!db_expression(&value)) { - db_error("No value\n"); - return; + db_error("No value\n"); + return; } - if (db_read_token() != tEOL) { - db_error("?\n"); - } + if (db_read_token() != tEOL) + db_error("?\n"); - db_write_variable(vp, &value); + db_write_variable(vp, value); } Index: head/sys/ddb/db_variables.h =================================================================== --- head/sys/ddb/db_variables.h (revision 131951) +++ head/sys/ddb/db_variables.h (revision 131952) @@ -1,57 +1,58 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. * * $FreeBSD$ */ /* * Author: David B. Golub, Carnegie Mellon University * Date: 7/90 */ #ifndef _DDB_DB_VARIABLES_H_ #define _DDB_DB_VARIABLES_H_ /* * Debugger variables. */ struct db_variable; typedef int db_varfcn_t(struct db_variable *vp, db_expr_t *valuep, int op); struct db_variable { char *name; /* Name of variable */ db_expr_t *valuep; /* value of variable */ /* function to call when reading/writing */ db_varfcn_t *fcn; #define DB_VAR_GET 0 #define DB_VAR_SET 1 }; #define FCN_NULL ((db_varfcn_t *)0) extern struct db_variable db_regs[]; /* machine registers */ extern struct db_variable *db_eregs; -void db_read_variable(struct db_variable *, db_expr_t *); +int db_read_variable(struct db_variable *, db_expr_t *); +int db_write_variable(struct db_variable *, db_expr_t); #endif /* _!DDB_DB_VARIABLES_H_ */ Index: head/sys/ddb/ddb.h =================================================================== --- head/sys/ddb/ddb.h (revision 131951) +++ head/sys/ddb/ddb.h (revision 131952) @@ -1,177 +1,153 @@ /*- * Copyright (c) 1993, Garrett A. Wollman. * Copyright (c) 1993, University of Vermont and State Agricultural College. * 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. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. * * $FreeBSD$ */ /* * Necessary declarations for the `ddb' kernel debugger. */ #ifndef _DDB_DDB_H_ #define _DDB_DDB_H_ #include /* type definitions */ #define DB_LINES_PER_PAGE 20 typedef void db_cmdfcn_t(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *modif); typedef void db_page_calloutfcn_t(void *arg); #define DB_COMMAND(cmd_name, func_name) \ DB_SET(cmd_name, func_name, db_cmd_set, 0, NULL) #define DB_SHOW_COMMAND(cmd_name, func_name) \ DB_SET(cmd_name, func_name, db_show_cmd_set, 0, NULL) #define DB_SET(cmd_name, func_name, set, flag, more) \ static db_cmdfcn_t func_name; \ \ static const struct command __CONCAT(func_name,_cmd) = { \ __STRING(cmd_name), \ func_name, \ flag, \ more \ }; \ TEXT_SET(set, __CONCAT(func_name,_cmd)); \ \ static void \ func_name(addr, have_addr, count, modif) \ db_expr_t addr; \ boolean_t have_addr; \ db_expr_t count; \ char *modif; -extern char *esym; extern db_expr_t db_maxoff; -extern int db_active; extern int db_indent; extern int db_inst_count; extern int db_load_count; extern int debugger_on_panic; extern int db_store_count; extern db_expr_t db_radix; extern db_expr_t db_max_width; extern db_expr_t db_tab_stop_width; +struct thread; struct vm_map; -#ifdef ALT_BREAK_TO_DEBUGGER -int db_alt_break(int, int *); -#endif void db_check_interrupt(void); void db_clear_watchpoints(void); db_addr_t db_disasm(db_addr_t loc, boolean_t altfmt); /* instruction disassembler */ void db_error(const char *s); int db_expression(db_expr_t *valuep); int db_get_variable(db_expr_t *valuep); void db_iprintf(const char *,...) __printflike(1, 2); struct vm_map *db_map_addr(vm_offset_t); boolean_t db_map_current(struct vm_map *); boolean_t db_map_equal(struct vm_map *, struct vm_map *); void db_print_loc_and_inst(db_addr_t loc); +void db_print_thread(void); void db_printf(const char *fmt, ...) __printflike(1, 2); -void db_read_bytes(vm_offset_t addr, size_t size, char *data); +int db_read_bytes(vm_offset_t addr, size_t size, char *data); /* machine-dependent */ int db_readline(char *lstart, int lsize); void db_restart_at_pc(boolean_t watchpt); +int db_set_variable(db_expr_t value); void db_set_watchpoints(void); void db_setup_paging(db_page_calloutfcn_t *callout, void *arg, int maxlines); void db_skip_to_eol(void); boolean_t db_stop_at_pc(boolean_t *is_breakpoint); #define db_strcpy strcpy -void db_trap(int type, int code); +void db_trace_self(void); +int db_trace_thread(struct thread *, int); int db_value_of_name(const char *name, db_expr_t *valuep); -void db_write_bytes(vm_offset_t addr, size_t size, char *data); - /* machine-dependent */ -void db_stack_thread(db_expr_t addr, boolean_t have_addr, - db_expr_t count, char *modif); -void kdb_init(void); +int db_write_bytes(vm_offset_t addr, size_t size, char *data); db_cmdfcn_t db_breakpoint_cmd; db_cmdfcn_t db_continue_cmd; db_cmdfcn_t db_delete_cmd; db_cmdfcn_t db_deletehwatch_cmd; db_cmdfcn_t db_deletewatch_cmd; db_cmdfcn_t db_examine_cmd; db_cmdfcn_t db_hwatchpoint_cmd; db_cmdfcn_t db_listbreak_cmd; db_cmdfcn_t db_print_cmd; db_cmdfcn_t db_ps; db_cmdfcn_t db_search_cmd; db_cmdfcn_t db_set_cmd; +db_cmdfcn_t db_set_thread; db_cmdfcn_t db_show_regs; +db_cmdfcn_t db_show_threads; db_cmdfcn_t db_single_step_cmd; db_cmdfcn_t db_stack_trace_cmd; db_cmdfcn_t db_trace_until_call_cmd; db_cmdfcn_t db_trace_until_matching_cmd; db_cmdfcn_t db_watchpoint_cmd; db_cmdfcn_t db_write_cmd; -db_cmdfcn_t db_show_one_thread; -#if 0 -db_cmdfcn_t db_help_cmd; -db_cmdfcn_t db_show_all_threads; -db_cmdfcn_t ipc_port_print; -db_cmdfcn_t vm_page_print; -#endif - db_page_calloutfcn_t db_simple_pager; -/* Scare the user with backtrace of curthread to console. */ -void db_print_backtrace(void); - /* * Command table. */ struct command { char * name; /* command name */ db_cmdfcn_t *fcn; /* function to call */ int flag; /* extra info: */ #define CS_OWN 0x1 /* non-standard syntax */ #define CS_MORE 0x2 /* standard syntax, but may have other words * at end */ #define CS_SET_DOT 0x100 /* set dot after command */ struct command *more; /* another level of command */ }; - -/* XXX: UGLY hack */ -#ifdef CN_DEAD -/* - * Routines to support GDB on an sio port. - */ -extern void *gdb_arg; -extern cn_getc_t *gdb_getc; -extern cn_putc_t *gdb_putc; -#endif #endif /* !_DDB_DDB_H_ */ Index: head/sys/i386/i386/db_interface.c =================================================================== --- head/sys/i386/i386/db_interface.c (revision 131951) +++ head/sys/i386/i386/db_interface.c (revision 131952) @@ -1,327 +1,144 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. */ #include __FBSDID("$FreeBSD$"); /* * Interface to new debugger. */ #include #include -#include #include +#include #include #include -#include #include -#ifdef SMP -#include /** CPUSTOP_ON_DDBBREAK */ -#endif #include #include #include -#include - -static jmp_buf *db_nofault = 0; -extern jmp_buf db_jmpbuf; - -extern void gdb_handle_exception(db_regs_t *, int, int); - -int db_active; -db_regs_t ddb_regs; - -static jmp_buf db_global_jmpbuf; - /* - * kdb_trap - field a TRACE or BPT trap + * Read bytes from kernel address space for debugger. */ int -kdb_trap(int type, int code, struct i386_saved_state *regs) +db_read_bytes(vm_offset_t addr, size_t size, char *data) { - u_int ef; - volatile int ddb_mode = !(boothowto & RB_GDB); + jmp_buf jb; + void *prev_jb; + char *src; + int ret; - /* - * XXX try to do nothing if the console is in graphics mode. - * Handle trace traps (and hardware breakpoints...) by ignoring - * them except for forgetting about them. Return 0 for other - * traps to say that we haven't done anything. The trap handler - * will usually panic. We should handle breakpoint traps for - * our breakpoints by disarming our breakpoints and fixing up - * %eip. - */ - if (cnunavailable() != 0 && ddb_mode) { - if (type == T_TRCTRAP) { - regs->tf_eflags &= ~PSL_T; - return (1); - } - return (0); + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + src = (char *)addr; + while (size-- > 0) + *data++ = *src++; } - - ef = read_eflags(); - disable_intr(); - -#ifdef SMP -#ifdef CPUSTOP_ON_DDBBREAK - -#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf("\nCPU%d stopping CPUs: 0x%08x...", PCPU_GET(cpuid), - PCPU_GET(other_cpus)); -#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ - - /* We stop all CPUs except ourselves (obviously) */ - stop_cpus(PCPU_GET(other_cpus)); - -#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf(" stopped.\n"); -#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ - -#endif /* CPUSTOP_ON_DDBBREAK */ -#endif /* SMP */ - - switch (type) { - case T_BPTFLT: /* breakpoint */ - case T_TRCTRAP: /* debug exception */ - break; - - default: - /* - * XXX this is almost useless now. In most cases, - * trap_fatal() has already printed a much more verbose - * message. However, it is dangerous to print things in - * trap_fatal() - printf() might be reentered and trap. - * The debugger should be given control first. - */ - if (ddb_mode) - db_printf("kernel: type %d trap, code=%x\n", type, code); - - if (db_nofault) { - jmp_buf *no_fault = db_nofault; - db_nofault = 0; - longjmp(*no_fault, 1); - } - } - - /* - * This handles unexpected traps in ddb commands, including calls to - * non-ddb functions. db_nofault only applies to memory accesses by - * internal ddb commands. - */ - if (db_active) - longjmp(db_global_jmpbuf, 1); - - /* - * XXX We really should switch to a local stack here. - */ - ddb_regs = *regs; - - /* - * If in kernel mode, esp and ss are not saved, so dummy them up. - */ - if (ISPL(regs->tf_cs) == 0) { - ddb_regs.tf_esp = (int)®s->tf_esp; - ddb_regs.tf_ss = rss(); - } - - (void) setjmp(db_global_jmpbuf); - if (ddb_mode) { - if (!db_active) - cndbctl(TRUE); - db_active = 1; - db_trap(type, code); - cndbctl(FALSE); - } else { - db_active = 1; - gdb_handle_exception(&ddb_regs, type, code); - } - db_active = 0; - - regs->tf_eip = ddb_regs.tf_eip; - regs->tf_eflags = ddb_regs.tf_eflags; - regs->tf_eax = ddb_regs.tf_eax; - regs->tf_ecx = ddb_regs.tf_ecx; - regs->tf_edx = ddb_regs.tf_edx; - regs->tf_ebx = ddb_regs.tf_ebx; - - /* - * If in user mode, the saved ESP and SS were valid, restore them. - */ - if (ISPL(regs->tf_cs)) { - regs->tf_esp = ddb_regs.tf_esp; - regs->tf_ss = ddb_regs.tf_ss & 0xffff; - } - - regs->tf_ebp = ddb_regs.tf_ebp; - regs->tf_esi = ddb_regs.tf_esi; - regs->tf_edi = ddb_regs.tf_edi; - regs->tf_es = ddb_regs.tf_es & 0xffff; - regs->tf_fs = ddb_regs.tf_fs & 0xffff; - regs->tf_cs = ddb_regs.tf_cs & 0xffff; - regs->tf_ds = ddb_regs.tf_ds & 0xffff; - -#ifdef SMP -#ifdef CPUSTOP_ON_DDBBREAK - -#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf("\nCPU%d restarting CPUs: 0x%08x...", PCPU_GET(cpuid), - stopped_cpus); -#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ - - /* Restart all the CPUs we previously stopped */ - if (stopped_cpus != PCPU_GET(other_cpus) && smp_started != 0) { - db_printf("whoa, other_cpus: 0x%08x, stopped_cpus: 0x%08x\n", - PCPU_GET(other_cpus), stopped_cpus); - panic("stop_cpus() failed"); - } - restart_cpus(stopped_cpus); - -#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf(" restarted.\n"); -#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ - -#endif /* CPUSTOP_ON_DDBBREAK */ -#endif /* SMP */ - - write_eflags(ef); - - return (1); + (void)kdb_jmpbuf(prev_jb); + return (ret); } /* - * Read bytes from kernel address space for debugger. - */ -void -db_read_bytes(vm_offset_t addr, size_t size, char *data) -{ - char *src; - - db_nofault = &db_jmpbuf; - - src = (char *)addr; - while (size-- > 0) - *data++ = *src++; - - db_nofault = 0; -} - -/* * Write bytes to kernel address space for debugger. */ -void +int db_write_bytes(vm_offset_t addr, size_t size, char *data) { - char *dst; + jmp_buf jb; + void *prev_jb; + char *dst; + pt_entry_t *ptep0 = NULL; + pt_entry_t oldmap0 = 0; + vm_offset_t addr1; + pt_entry_t *ptep1 = NULL; + pt_entry_t oldmap1 = 0; + int ret; - pt_entry_t *ptep0 = NULL; - pt_entry_t oldmap0 = 0; - vm_offset_t addr1; - pt_entry_t *ptep1 = NULL; - pt_entry_t oldmap1 = 0; + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + if (addr > trunc_page((vm_offset_t)btext) - size && + addr < round_page((vm_offset_t)etext)) { - db_nofault = &db_jmpbuf; + ptep0 = pmap_pte(kernel_pmap, addr); + oldmap0 = *ptep0; + *ptep0 |= PG_RW; - if (addr > trunc_page((vm_offset_t)btext) - size && - addr < round_page((vm_offset_t)etext)) { + /* + * Map another page if the data crosses a page + * boundary. + */ + if ((*ptep0 & PG_PS) == 0) { + addr1 = trunc_page(addr + size - 1); + if (trunc_page(addr) != addr1) { + ptep1 = pmap_pte(kernel_pmap, addr1); + oldmap1 = *ptep1; + *ptep1 |= PG_RW; + } + } else { + addr1 = trunc_4mpage(addr + size - 1); + if (trunc_4mpage(addr) != addr1) { + ptep1 = pmap_pte(kernel_pmap, addr1); + oldmap1 = *ptep1; + *ptep1 |= PG_RW; + } + } - ptep0 = pmap_pte(kernel_pmap, addr); - oldmap0 = *ptep0; - *ptep0 |= PG_RW; - - /* Map another page if the data crosses a page boundary. */ - if ((*ptep0 & PG_PS) == 0) { - addr1 = trunc_page(addr + size - 1); - if (trunc_page(addr) != addr1) { - ptep1 = pmap_pte(kernel_pmap, addr1); - oldmap1 = *ptep1; - *ptep1 |= PG_RW; - } - } else { - addr1 = trunc_4mpage(addr + size - 1); - if (trunc_4mpage(addr) != addr1) { - ptep1 = pmap_pte(kernel_pmap, addr1); - oldmap1 = *ptep1; - *ptep1 |= PG_RW; + invltlb(); } - } - invltlb(); + dst = (char *)addr; + + while (size-- > 0) + *dst++ = *data++; } - dst = (char *)addr; + (void)kdb_jmpbuf(prev_jb); - while (size-- > 0) - *dst++ = *data++; - - db_nofault = 0; - if (ptep0) { - *ptep0 = oldmap0; + *ptep0 = oldmap0; - if (ptep1) - *ptep1 = oldmap1; + if (ptep1) + *ptep1 = oldmap1; - invltlb(); + invltlb(); } -} -/* - * XXX - * Move this to machdep.c and allow it to be called if any debugger is - * installed. - */ -void -Debugger(const char *msg) -{ - static volatile u_int in_Debugger; - - /* - * XXX - * Do nothing if the console is in graphics mode. This is - * OK if the call is for the debugger hotkey but not if the call - * is a weak form of panicing. - */ - if (cnunavailable() != 0 && !(boothowto & RB_GDB)) - return; - - if (atomic_cmpset_acq_int(&in_Debugger, 0, 1)) { - db_printf("Debugger(\"%s\")\n", msg); - breakpoint(); - atomic_store_rel_int(&in_Debugger, 0); - } + return (ret); } void db_show_mdpcpu(struct pcpu *pc) { db_printf("APIC ID = %d\n", pc->pc_apic_id); db_printf("currentldt = 0x%x\n", pc->pc_currentldt); } Index: head/sys/i386/i386/db_trace.c =================================================================== --- head/sys/i386/i386/db_trace.c (revision 131951) +++ head/sys/i386/i386/db_trace.c (revision 131952) @@ -1,710 +1,673 @@ /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. */ #include __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include -db_varfcn_t db_dr0; -db_varfcn_t db_dr1; -db_varfcn_t db_dr2; -db_varfcn_t db_dr3; -db_varfcn_t db_dr4; -db_varfcn_t db_dr5; -db_varfcn_t db_dr6; -db_varfcn_t db_dr7; +static db_varfcn_t db_dr0; +static db_varfcn_t db_dr1; +static db_varfcn_t db_dr2; +static db_varfcn_t db_dr3; +static db_varfcn_t db_dr4; +static db_varfcn_t db_dr5; +static db_varfcn_t db_dr6; +static db_varfcn_t db_dr7; +static db_varfcn_t db_esp; +static db_varfcn_t db_frame; +static db_varfcn_t db_ss; /* * Machine register set. */ +#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) struct db_variable db_regs[] = { - { "cs", &ddb_regs.tf_cs, FCN_NULL }, - { "ds", &ddb_regs.tf_ds, FCN_NULL }, - { "es", &ddb_regs.tf_es, FCN_NULL }, - { "fs", &ddb_regs.tf_fs, FCN_NULL }, -#if 0 - { "gs", &ddb_regs.tf_gs, FCN_NULL }, -#endif - { "ss", &ddb_regs.tf_ss, FCN_NULL }, - { "eax", &ddb_regs.tf_eax, FCN_NULL }, - { "ecx", &ddb_regs.tf_ecx, FCN_NULL }, - { "edx", &ddb_regs.tf_edx, FCN_NULL }, - { "ebx", &ddb_regs.tf_ebx, FCN_NULL }, - { "esp", &ddb_regs.tf_esp, FCN_NULL }, - { "ebp", &ddb_regs.tf_ebp, FCN_NULL }, - { "esi", &ddb_regs.tf_esi, FCN_NULL }, - { "edi", &ddb_regs.tf_edi, FCN_NULL }, - { "eip", &ddb_regs.tf_eip, FCN_NULL }, - { "efl", &ddb_regs.tf_eflags, FCN_NULL }, - { "dr0", NULL, db_dr0 }, - { "dr1", NULL, db_dr1 }, - { "dr2", NULL, db_dr2 }, - { "dr3", NULL, db_dr3 }, - { "dr4", NULL, db_dr4 }, - { "dr5", NULL, db_dr5 }, - { "dr6", NULL, db_dr6 }, - { "dr7", NULL, db_dr7 }, + { "cs", DB_OFFSET(tf_cs), db_frame }, + { "ds", DB_OFFSET(tf_ds), db_frame }, + { "es", DB_OFFSET(tf_es), db_frame }, + { "fs", DB_OFFSET(tf_fs), db_frame }, + { "ss", NULL, db_ss }, + { "eax", DB_OFFSET(tf_eax), db_frame }, + { "ecx", DB_OFFSET(tf_ecx), db_frame }, + { "edx", DB_OFFSET(tf_edx), db_frame }, + { "ebx", DB_OFFSET(tf_ebx), db_frame }, + { "esp", NULL, db_esp }, + { "ebp", DB_OFFSET(tf_ebp), db_frame }, + { "esi", DB_OFFSET(tf_esi), db_frame }, + { "edi", DB_OFFSET(tf_edi), db_frame }, + { "eip", DB_OFFSET(tf_eip), db_frame }, + { "efl", DB_OFFSET(tf_eflags), db_frame }, + { "dr0", NULL, db_dr0 }, + { "dr1", NULL, db_dr1 }, + { "dr2", NULL, db_dr2 }, + { "dr3", NULL, db_dr3 }, + { "dr4", NULL, db_dr4 }, + { "dr5", NULL, db_dr5 }, + { "dr6", NULL, db_dr6 }, + { "dr7", NULL, db_dr7 }, }; struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); +#define DB_DRX_FUNC(reg) \ +static int \ +db_ ## reg (vp, valuep, op) \ + struct db_variable *vp; \ + db_expr_t * valuep; \ + int op; \ +{ \ + if (op == DB_VAR_GET) \ + *valuep = r ## reg (); \ + else \ + load_ ## reg (*valuep); \ + return (1); \ +} + +DB_DRX_FUNC(dr0) +DB_DRX_FUNC(dr1) +DB_DRX_FUNC(dr2) +DB_DRX_FUNC(dr3) +DB_DRX_FUNC(dr4) +DB_DRX_FUNC(dr5) +DB_DRX_FUNC(dr6) +DB_DRX_FUNC(dr7) + +static __inline int +get_esp(struct trapframe *tf) +{ + return ((ISPL(tf->tf_cs)) ? tf->tf_esp : + (db_expr_t)tf + (uintptr_t)DB_OFFSET(tf_esp)); +} + +static int +db_frame(struct db_variable *vp, db_expr_t *valuep, int op) +{ + int *reg; + + if (kdb_frame == NULL) + return (0); + + reg = (int *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep); + if (op == DB_VAR_GET) + *valuep = *reg; + else + *reg = *valuep; + return (1); +} + +static int +db_esp(struct db_variable *vp, db_expr_t *valuep, int op) +{ + + if (kdb_frame == NULL) + return (0); + + if (op == DB_VAR_GET) + *valuep = get_esp(kdb_frame); + else if (ISPL(kdb_frame->tf_cs)) + kdb_frame->tf_esp = *valuep; + return (1); +} + +static int +db_ss(struct db_variable *vp, db_expr_t *valuep, int op) +{ + + if (kdb_frame == NULL) + return (0); + + if (op == DB_VAR_GET) + *valuep = (ISPL(kdb_frame->tf_cs)) ? kdb_frame->tf_ss : rss(); + else if (ISPL(kdb_frame->tf_cs)) + kdb_frame->tf_ss = *valuep; + return (1); +} + /* * Stack trace. */ #define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK) struct i386_frame { struct i386_frame *f_frame; int f_retaddr; int f_arg0; }; #define NORMAL 0 #define TRAP 1 #define INTERRUPT 2 #define SYSCALL 3 -static void db_nextframe(struct i386_frame **, db_addr_t *, struct proc *); +static void db_nextframe(struct i386_frame **, db_addr_t *, struct thread *); static int db_numargs(struct i386_frame *); static void db_print_stack_entry(const char *, int, char **, int *, db_addr_t); -static void decode_syscall(int, struct proc *); -static void db_trace_one_stack(int count, boolean_t have_addr, - struct proc *p, struct i386_frame *frame, db_addr_t callpc); +static void decode_syscall(int, struct thread *); - static char * watchtype_str(int type); int i386_set_watch(int watchnum, unsigned int watchaddr, int size, int access, struct dbreg * d); int i386_clr_watch(int watchnum, struct dbreg * d); int db_md_set_watchpoint(db_expr_t addr, db_expr_t size); int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size); void db_md_list_watchpoints(void); - /* * Figure out how many arguments were passed into the frame at "fp". */ static int db_numargs(fp) struct i386_frame *fp; { int *argp; int inst; int args; argp = (int *)db_get_value((int)&fp->f_retaddr, 4, FALSE); /* * XXX etext is wrong for LKMs. We should attempt to interpret * the instruction at the return address in all cases. This * may require better fault handling. */ if (argp < (int *)btext || argp >= (int *)etext) { args = 5; } else { inst = db_get_value((int)argp, 4, FALSE); if ((inst & 0xff) == 0x59) /* popl %ecx */ args = 1; else if ((inst & 0xffff) == 0xc483) /* addl $Ibs, %esp */ args = ((inst >> 16) & 0xff) / 4; else args = 5; } return (args); } static void db_print_stack_entry(name, narg, argnp, argp, callpc) const char *name; int narg; char **argnp; int *argp; db_addr_t callpc; { db_printf("%s(", name); while (narg) { if (argnp) db_printf("%s=", *argnp++); db_printf("%r", db_get_value((int)argp, 4, FALSE)); argp++; if (--narg != 0) db_printf(","); } db_printf(") at "); db_printsym(callpc, DB_STGY_PROC); db_printf("\n"); } static void -decode_syscall(number, p) - int number; - struct proc *p; +decode_syscall(int number, struct thread *td) { + struct proc *p; c_db_sym_t sym; db_expr_t diff; sy_call_t *f; const char *symname; db_printf(" (%d", number); + p = (td != NULL) ? td->td_proc : NULL; if (p != NULL && 0 <= number && number < p->p_sysent->sv_size) { f = p->p_sysent->sv_table[number].sy_call; sym = db_search_symbol((db_addr_t)f, DB_STGY_ANY, &diff); if (sym != DB_SYM_NULL && diff == 0) { db_symbol_values(sym, &symname, NULL); db_printf(", %s, %s", p->p_sysent->sv_name, symname); } } db_printf(")"); } /* * Figure out the next frame up in the call stack. */ static void -db_nextframe(fp, ip, p) - struct i386_frame **fp; /* in/out */ - db_addr_t *ip; /* out */ - struct proc *p; /* in */ +db_nextframe(struct i386_frame **fp, db_addr_t *ip, struct thread *td) { struct trapframe *tf; int frame_type; int eip, esp, ebp; db_expr_t offset; c_db_sym_t sym; const char *name; eip = db_get_value((int) &(*fp)->f_retaddr, 4, FALSE); ebp = db_get_value((int) &(*fp)->f_frame, 4, FALSE); /* * Figure out frame type. */ frame_type = NORMAL; sym = db_search_symbol(eip, DB_STGY_ANY, &offset); db_symbol_values(sym, &name, NULL); if (name != NULL) { if (strcmp(name, "calltrap") == 0 || strcmp(name, "fork_trampoline") == 0) frame_type = TRAP; else if (strncmp(name, "Xatpic_intr", 11) == 0 || strncmp(name, "Xapic_isr", 9) == 0) frame_type = INTERRUPT; else if (strcmp(name, "Xlcall_syscall") == 0 || strcmp(name, "Xint0x80_syscall") == 0) frame_type = SYSCALL; } /* * Normal frames need no special processing. */ if (frame_type == NORMAL) { *ip = (db_addr_t) eip; *fp = (struct i386_frame *) ebp; return; } db_print_stack_entry(name, 0, 0, 0, eip); /* * Point to base of trapframe which is just above the * current frame. */ if (frame_type == INTERRUPT) tf = (struct trapframe *)((int)*fp + 12); else tf = (struct trapframe *)((int)*fp + 8); if (INKERNEL((int) tf)) { - esp = (ISPL(tf->tf_cs) == SEL_UPL) ? - tf->tf_esp : (int)&tf->tf_esp; + esp = get_esp(tf); eip = tf->tf_eip; ebp = tf->tf_ebp; switch (frame_type) { case TRAP: db_printf("--- trap %#r", tf->tf_trapno); break; case SYSCALL: db_printf("--- syscall"); - decode_syscall(tf->tf_eax, p); + decode_syscall(tf->tf_eax, td); break; case INTERRUPT: db_printf("--- interrupt"); break; default: panic("The moon has moved again."); } db_printf(", eip = %#r, esp = %#r, ebp = %#r ---\n", eip, esp, ebp); } *ip = (db_addr_t) eip; *fp = (struct i386_frame *) ebp; } -void -db_stack_trace_cmd(addr, have_addr, count, modif) - db_expr_t addr; - boolean_t have_addr; - db_expr_t count; - char *modif; +static int +db_backtrace(struct thread *td, struct trapframe *tf, struct i386_frame *frame, + db_addr_t pc, int count) { - struct i386_frame *frame; - struct proc *p; - struct pcb *pcb; - struct thread *td; - db_addr_t callpc; - pid_t pid; + struct i386_frame *actframe; +#define MAXNARG 16 + char *argnames[MAXNARG], **argnp = NULL; + const char *name; + int *argp; + db_expr_t offset; + c_db_sym_t sym; + int narg; + boolean_t first; if (count == -1) count = 1024; - if (!have_addr) { - td = curthread; - p = td->td_proc; - frame = (struct i386_frame *)ddb_regs.tf_ebp; - if (frame == NULL) - frame = (struct i386_frame *)(ddb_regs.tf_esp - 4); - callpc = (db_addr_t)ddb_regs.tf_eip; - } else if (!INKERNEL(addr)) { - pid = (addr % 16) + ((addr >> 4) % 16) * 10 + - ((addr >> 8) % 16) * 100 + ((addr >> 12) % 16) * 1000 + - ((addr >> 16) % 16) * 10000; - /* - * The pcb for curproc is not valid at this point, - * so fall back to the default case. - */ - if (pid == curthread->td_proc->p_pid) { - td = curthread; - p = td->td_proc; - frame = (struct i386_frame *)ddb_regs.tf_ebp; - if (frame == NULL) - frame = (struct i386_frame *) - (ddb_regs.tf_esp - 4); - callpc = (db_addr_t)ddb_regs.tf_eip; - } else { - - /* sx_slock(&allproc_lock); */ - LIST_FOREACH(p, &allproc, p_list) { - if (p->p_pid == pid) - break; - } - /* sx_sunlock(&allproc_lock); */ - if (p == NULL) { - db_printf("pid %d not found\n", pid); - return; - } - if ((p->p_sflag & PS_INMEM) == 0) { - db_printf("pid %d swapped out\n", pid); - return; - } - pcb = FIRST_THREAD_IN_PROC(p)->td_pcb; /* XXXKSE */ - frame = (struct i386_frame *)pcb->pcb_ebp; - if (frame == NULL) - frame = (struct i386_frame *) - (pcb->pcb_esp - 4); - callpc = (db_addr_t)pcb->pcb_eip; - } - } else { - p = NULL; - frame = (struct i386_frame *)addr; - callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE); - frame = frame->f_frame; - } - db_trace_one_stack(count, have_addr, p, frame, callpc); -} - -void -db_stack_thread(db_expr_t addr, boolean_t have_addr, - db_expr_t count, char *modif) -{ - struct i386_frame *frame; - struct thread *td; - struct proc *p; - struct pcb *pcb; - db_addr_t callpc; - - if (!have_addr) - return; - if (!INKERNEL(addr)) { - printf("bad thread address"); - return; - } - td = (struct thread *)addr; - /* quick sanity check */ - if ((p = td->td_proc) != td->td_ksegrp->kg_proc) - return; - if (TD_IS_SWAPPED(td)) { - db_printf("thread at %p swapped out\n", td); - return; - } - if (td == curthread) { - frame = (struct i386_frame *)ddb_regs.tf_ebp; - if (frame == NULL) - frame = (struct i386_frame *)(ddb_regs.tf_esp - 4); - callpc = (db_addr_t)ddb_regs.tf_eip; - } else { - pcb = td->td_pcb; - frame = (struct i386_frame *)pcb->pcb_ebp; - if (frame == NULL) - frame = (struct i386_frame *) (pcb->pcb_esp - 4); - callpc = (db_addr_t)pcb->pcb_eip; - } - db_trace_one_stack(count, have_addr, p, frame, callpc); -} - -static void -db_trace_one_stack(int count, boolean_t have_addr, - struct proc *p, struct i386_frame *frame, db_addr_t callpc) -{ - int *argp; - boolean_t first; - first = TRUE; while (count--) { - struct i386_frame *actframe; - int narg; - const char * name; - db_expr_t offset; - c_db_sym_t sym; -#define MAXNARG 16 - char *argnames[MAXNARG], **argnp = NULL; - - sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); + sym = db_search_symbol(pc, DB_STGY_ANY, &offset); db_symbol_values(sym, &name, NULL); /* * Attempt to determine a (possibly fake) frame that gives * the caller's pc. It may differ from `frame' if the * current function never sets up a standard frame or hasn't * set one up yet or has just discarded one. The last two * cases can be guessed fairly reliably for code generated * by gcc. The first case is too much trouble to handle in * general because the amount of junk on the stack depends * on the pc (the special handling of "calltrap", etc. in * db_nextframe() works because the `next' pc is special). */ actframe = frame; if (first) { - if (!have_addr) { + if (tf != NULL) { int instr; - instr = db_get_value(callpc, 4, FALSE); - if ((instr & 0x00ffffff) == 0x00e58955) { + instr = db_get_value(pc, 4, FALSE); + if ((instr & 0xffffff) == 0x00e58955) { /* pushl %ebp; movl %esp, %ebp */ - actframe = (struct i386_frame *) - (ddb_regs.tf_esp - 4); - } else if ((instr & 0x0000ffff) == 0x0000e589) { + actframe = (void *)(get_esp(tf) - 4); + } else if ((instr & 0xffff) == 0x0000e589) { /* movl %esp, %ebp */ - actframe = (struct i386_frame *) - ddb_regs.tf_esp; - if (ddb_regs.tf_ebp == 0) { - /* Fake caller's frame better. */ + actframe = (void *)get_esp(tf); + if (tf->tf_ebp == 0) { + /* Fake frame better. */ frame = actframe; } - } else if ((instr & 0x000000ff) == 0x000000c3) { + } else if ((instr & 0xff) == 0x000000c3) { /* ret */ - actframe = (struct i386_frame *) - (ddb_regs.tf_esp - 4); + actframe = (void *)(get_esp(tf) - 4); } else if (offset == 0) { - /* Probably a symbol in assembler code. */ - actframe = (struct i386_frame *) - (ddb_regs.tf_esp - 4); + /* Probably an assembler symbol. */ + actframe = (void *)(get_esp(tf) - 4); } } else if (strcmp(name, "fork_trampoline") == 0) { /* * Don't try to walk back on a stack for a * process that hasn't actually been run yet. */ - db_print_stack_entry(name, 0, 0, 0, callpc); + db_print_stack_entry(name, 0, 0, 0, pc); break; } first = FALSE; } argp = &actframe->f_arg0; narg = MAXNARG; if (sym != NULL && db_sym_numargs(sym, &narg, argnames)) { argnp = argnames; } else { narg = db_numargs(frame); } - db_print_stack_entry(name, narg, argnp, argp, callpc); + db_print_stack_entry(name, narg, argnp, argp, pc); if (actframe != frame) { /* `frame' belongs to caller. */ - callpc = (db_addr_t) + pc = (db_addr_t) db_get_value((int)&actframe->f_retaddr, 4, FALSE); continue; } - db_nextframe(&frame, &callpc, p); + db_nextframe(&frame, &pc, td); - if (INKERNEL((int) callpc) && !INKERNEL((int) frame)) { - sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); + if (INKERNEL((int)pc) && !INKERNEL((int) frame)) { + sym = db_search_symbol(pc, DB_STGY_ANY, &offset); db_symbol_values(sym, &name, NULL); - db_print_stack_entry(name, 0, 0, 0, callpc); + db_print_stack_entry(name, 0, 0, 0, pc); break; } if (!INKERNEL((int) frame)) { break; } } + + return (0); } void -db_print_backtrace(void) +db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, + char *modif) { + struct thread *td; + + td = (have_addr) ? kdb_thr_lookup(addr) : kdb_thread; + if (td == NULL) { + db_printf("Thread %d not found\n", addr); + return; + } + db_trace_thread(td, count); +} + +void +db_trace_self(void) +{ + struct i386_frame *frame; + db_addr_t callpc; register_t ebp; __asm __volatile("movl %%ebp,%0" : "=r" (ebp)); - db_stack_trace_cmd(ebp, 1, -1, NULL); + frame = (struct i386_frame *)ebp; + callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE); + frame = frame->f_frame; + db_backtrace(curthread, NULL, frame, callpc, -1); } -#define DB_DRX_FUNC(reg) \ -int \ -db_ ## reg (vp, valuep, op) \ - struct db_variable *vp; \ - db_expr_t * valuep; \ - int op; \ -{ \ - if (op == DB_VAR_GET) \ - *valuep = r ## reg (); \ - else \ - load_ ## reg (*valuep); \ - return (0); \ -} +int +db_trace_thread(struct thread *thr, int count) +{ + struct pcb *ctx; -DB_DRX_FUNC(dr0) -DB_DRX_FUNC(dr1) -DB_DRX_FUNC(dr2) -DB_DRX_FUNC(dr3) -DB_DRX_FUNC(dr4) -DB_DRX_FUNC(dr5) -DB_DRX_FUNC(dr6) -DB_DRX_FUNC(dr7) + ctx = kdb_thr_ctx(thr); + return (db_backtrace(thr, NULL, (struct i386_frame *)ctx->pcb_ebp, + ctx->pcb_eip, count)); +} int i386_set_watch(watchnum, watchaddr, size, access, d) int watchnum; unsigned int watchaddr; int size; int access; struct dbreg * d; { int i; unsigned int mask; if (watchnum == -1) { for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2) if ((d->dr[7] & mask) == 0) break; if (i < 4) watchnum = i; else return (-1); } switch (access) { case DBREG_DR7_EXEC: size = 1; /* size must be 1 for an execution breakpoint */ /* fall through */ case DBREG_DR7_WRONLY: case DBREG_DR7_RDWR: break; default : return (-1); } /* * we can watch a 1, 2, or 4 byte sized location */ switch (size) { case 1 : mask = 0x00; break; case 2 : mask = 0x01 << 2; break; case 4 : mask = 0x03 << 2; break; default : return (-1); } mask |= access; /* clear the bits we are about to affect */ d->dr[7] &= ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16))); /* set drN register to the address, N=watchnum */ DBREG_DRX(d,watchnum) = watchaddr; /* enable the watchpoint */ d->dr[7] |= (0x2 << (watchnum*2)) | (mask << (watchnum*4+16)); return (watchnum); } int i386_clr_watch(watchnum, d) int watchnum; struct dbreg * d; { if (watchnum < 0 || watchnum >= 4) return (-1); d->dr[7] = d->dr[7] & ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16))); DBREG_DRX(d,watchnum) = 0; return (0); } int db_md_set_watchpoint(addr, size) db_expr_t addr; db_expr_t size; { int avail, wsize; int i; struct dbreg d; fill_dbregs(NULL, &d); avail = 0; for(i=0; i<4; i++) { if ((d.dr[7] & (3 << (i*2))) == 0) avail++; } if (avail*4 < size) return (-1); for (i=0; i<4 && (size != 0); i++) { if ((d.dr[7] & (3<<(i*2))) == 0) { if (size > 4) wsize = 4; else wsize = size; if (wsize == 3) wsize++; i386_set_watch(i, addr, wsize, DBREG_DR7_WRONLY, &d); addr += wsize; size -= wsize; } } set_dbregs(NULL, &d); return(0); } int db_md_clr_watchpoint(addr, size) db_expr_t addr; db_expr_t size; { int i; struct dbreg d; fill_dbregs(NULL, &d); for(i=0; i<4; i++) { if (d.dr[7] & (3 << (i*2))) { if ((DBREG_DRX((&d), i) >= addr) && (DBREG_DRX((&d), i) < addr+size)) i386_clr_watch(i, &d); } } set_dbregs(NULL, &d); return(0); } static char * watchtype_str(type) int type; { switch (type) { case DBREG_DR7_EXEC : return "execute"; break; case DBREG_DR7_RDWR : return "read/write"; break; case DBREG_DR7_WRONLY : return "write"; break; default : return "invalid"; break; } } void db_md_list_watchpoints() { int i; struct dbreg d; fill_dbregs(NULL, &d); db_printf("\nhardware watchpoints:\n"); db_printf(" watch status type len address\n"); db_printf(" ----- -------- ---------- --- ----------\n"); for (i=0; i<4; i++) { if (d.dr[7] & (0x03 << (i*2))) { unsigned type, len; type = (d.dr[7] >> (16+(i*4))) & 3; len = (d.dr[7] >> (16+(i*4)+2)) & 3; db_printf(" %-5d %-8s %10s %3d 0x%08x\n", i, "enabled", watchtype_str(type), len+1, DBREG_DRX((&d),i)); } else { db_printf(" %-5d disabled\n", i); } } db_printf("\ndebug register values:\n"); for (i=0; i<8; i++) { db_printf(" dr%d 0x%08x\n", i, DBREG_DRX((&d),i)); } db_printf("\n"); } Index: head/sys/i386/include/db_machdep.h =================================================================== --- head/sys/i386/include/db_machdep.h (revision 131951) +++ head/sys/i386/include/db_machdep.h (revision 131952) @@ -1,93 +1,86 @@ /* * Mach Operating System * Copyright (c) 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. * * $FreeBSD$ */ #ifndef _MACHINE_DB_MACHDEP_H_ #define _MACHINE_DB_MACHDEP_H_ #include -#include #include -#define i386_saved_state trapframe - typedef vm_offset_t db_addr_t; /* address - unsigned */ typedef int db_expr_t; /* expression - signed */ -typedef struct i386_saved_state db_regs_t; -extern db_regs_t ddb_regs; /* register state */ -#define DDB_REGS (&ddb_regs) +#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_eip) -#define PC_REGS(regs) ((db_addr_t)(regs)->tf_eip) - #define BKPT_INST 0xcc /* breakpoint instruction */ #define BKPT_SIZE (1) /* size of breakpoint inst */ #define BKPT_SET(inst) (BKPT_INST) -#define BKPT_SKIP ddb_regs.tf_eip += 1 +#define BKPT_SKIP kdb_frame->tf_eip += 1 -#define FIXUP_PC_AFTER_BREAK ddb_regs.tf_eip -= 1; +#define FIXUP_PC_AFTER_BREAK kdb_frame->tf_eip -= 1; -#define db_clear_single_step(regs) ((regs)->tf_eflags &= ~PSL_T) -#define db_set_single_step(regs) ((regs)->tf_eflags |= PSL_T) +#define db_clear_single_step kdb_cpu_clear_singlestep +#define db_set_single_step kdb_cpu_set_singlestep #define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT) /* * Watchpoints are not supported. The debug exception type is in %dr6 * and not yet in the args to this macro. */ #define IS_WATCHPOINT_TRAP(type, code) 0 #define I_CALL 0xe8 #define I_CALLI 0xff #define I_RET 0xc3 #define I_IRET 0xcf #define inst_trap_return(ins) (((ins)&0xff) == I_IRET) #define inst_return(ins) (((ins)&0xff) == I_RET) #define inst_call(ins) (((ins)&0xff) == I_CALL || \ (((ins)&0xff) == I_CALLI && \ ((ins)&0x3800) == 0x1000)) #define inst_load(ins) 0 #define inst_store(ins) 0 /* * There no interesting addresses below _kstack = 0xefbfe000. There * are small absolute values for GUPROF, but we don't want to see them. * Treat "negative" addresses below _kstack as non-small to allow for * future reductions of _kstack and to avoid sign extension problems. * * There is one interesting symbol above -db_maxoff = 0xffff0000, * namely _APTD = 0xfffff000. Accepting this would mess up the * printing of small negative offsets. The next largest symbol is * _APTmap = 0xffc00000. Accepting this is OK (unless db_maxoff is * set to >= 0x400000 - (max stack offset)). */ #define DB_SMALL_VALUE_MAX 0x7fffffff #define DB_SMALL_VALUE_MIN (-0x400001) #endif /* !_MACHINE_DB_MACHDEP_H_ */ Index: head/sys/ia64/ia64/db_interface.c =================================================================== --- head/sys/ia64/ia64/db_interface.c (revision 131951) +++ head/sys/ia64/ia64/db_interface.c (revision 131952) @@ -1,568 +1,449 @@ -/* $FreeBSD$ */ - /* * Mach Operating System * Copyright (c) 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 * 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 the * rights to redistribute these changes. * * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) */ -/* - * Parts of this file are derived from Mach 3: - * - * File: alpha_instruction.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 6/92 - */ +#include +__FBSDID("$FreeBSD$"); /* * Interface to DDB. */ #include -#include -#include #include -#include -#include #include +#include #include +#include +#include +#include +#include #include #include +#include #include #include #include #include #include #include #include -static jmp_buf *db_nofault = 0; -extern jmp_buf db_jmpbuf; +#define TMPL_BITS 5 +#define TMPL_MASK ((1 << TMPL_BITS) - 1) +#define SLOT_BITS 41 +#define SLOT_COUNT 3 +#define SLOT_MASK ((1ULL << SLOT_BITS) - 1ULL) +#define SLOT_SHIFT(i) (TMPL_BITS+((i)<<3)+(i)) -extern void gdb_handle_exception(db_regs_t *, int); +static db_varfcn_t db_frame; +static db_varfcn_t db_getrse; +static db_varfcn_t db_getip; -int db_active; -db_regs_t ddb_regs; - -static int db_get_rse_reg(struct db_variable *vp, db_expr_t *valuep, int op); -static int db_get_ip_reg(struct db_variable *vp, db_expr_t *valuep, int op); - +#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) struct db_variable db_regs[] = { - /* Misc control/app registers */ -#define DB_MISC_REGS 13 /* make sure this is correct */ - - {"ip", NULL, db_get_ip_reg}, - {"psr", (db_expr_t*) &ddb_regs.tf_special.psr, FCN_NULL}, - {"cr.isr", (db_expr_t*) &ddb_regs.tf_special.isr, FCN_NULL}, - {"cr.ifa", (db_expr_t*) &ddb_regs.tf_special.ifa, FCN_NULL}, - {"pr", (db_expr_t*) &ddb_regs.tf_special.pr, FCN_NULL}, - {"ar.rsc", (db_expr_t*) &ddb_regs.tf_special.rsc, FCN_NULL}, - {"ar.pfs", (db_expr_t*) &ddb_regs.tf_special.pfs, FCN_NULL}, - {"cr.ifs", (db_expr_t*) &ddb_regs.tf_special.cfm, FCN_NULL}, - {"ar.bspstore", (db_expr_t*) &ddb_regs.tf_special.bspstore, FCN_NULL}, - {"ndirty", (db_expr_t*) &ddb_regs.tf_special.ndirty, FCN_NULL}, - {"ar.rnat", (db_expr_t*) &ddb_regs.tf_special.rnat, FCN_NULL}, - {"ar.unat", (db_expr_t*) &ddb_regs.tf_special.unat, FCN_NULL}, - {"ar.fpsr", (db_expr_t*) &ddb_regs.tf_special.fpsr, FCN_NULL}, - - /* Branch registers */ - {"rp", (db_expr_t*) &ddb_regs.tf_special.rp, FCN_NULL}, - /* b1, b2, b3, b4, b5 are preserved */ - {"b6", (db_expr_t*) &ddb_regs.tf_scratch.br6, FCN_NULL}, - {"b7", (db_expr_t*) &ddb_regs.tf_scratch.br7, FCN_NULL}, - - /* Static registers */ - {"gp", (db_expr_t*) &ddb_regs.tf_special.gp, FCN_NULL}, - {"r2", (db_expr_t*) &ddb_regs.tf_scratch.gr2, FCN_NULL}, - {"r3", (db_expr_t*) &ddb_regs.tf_scratch.gr3, FCN_NULL}, - {"r8", (db_expr_t*) &ddb_regs.tf_scratch.gr8, FCN_NULL}, - {"r9", (db_expr_t*) &ddb_regs.tf_scratch.gr9, FCN_NULL}, - {"r10", (db_expr_t*) &ddb_regs.tf_scratch.gr10, FCN_NULL}, - {"r11", (db_expr_t*) &ddb_regs.tf_scratch.gr11, FCN_NULL}, - {"sp", (db_expr_t*) &ddb_regs.tf_special.sp, FCN_NULL}, - {"tp", (db_expr_t*) &ddb_regs.tf_special.tp, FCN_NULL}, - {"r14", (db_expr_t*) &ddb_regs.tf_scratch.gr14, FCN_NULL}, - {"r15", (db_expr_t*) &ddb_regs.tf_scratch.gr15, FCN_NULL}, - {"r16", (db_expr_t*) &ddb_regs.tf_scratch.gr16, FCN_NULL}, - {"r17", (db_expr_t*) &ddb_regs.tf_scratch.gr17, FCN_NULL}, - {"r18", (db_expr_t*) &ddb_regs.tf_scratch.gr18, FCN_NULL}, - {"r19", (db_expr_t*) &ddb_regs.tf_scratch.gr19, FCN_NULL}, - {"r20", (db_expr_t*) &ddb_regs.tf_scratch.gr20, FCN_NULL}, - {"r21", (db_expr_t*) &ddb_regs.tf_scratch.gr21, FCN_NULL}, - {"r22", (db_expr_t*) &ddb_regs.tf_scratch.gr22, FCN_NULL}, - {"r23", (db_expr_t*) &ddb_regs.tf_scratch.gr23, FCN_NULL}, - {"r24", (db_expr_t*) &ddb_regs.tf_scratch.gr24, FCN_NULL}, - {"r25", (db_expr_t*) &ddb_regs.tf_scratch.gr25, FCN_NULL}, - {"r26", (db_expr_t*) &ddb_regs.tf_scratch.gr26, FCN_NULL}, - {"r27", (db_expr_t*) &ddb_regs.tf_scratch.gr27, FCN_NULL}, - {"r28", (db_expr_t*) &ddb_regs.tf_scratch.gr28, FCN_NULL}, - {"r29", (db_expr_t*) &ddb_regs.tf_scratch.gr29, FCN_NULL}, - {"r30", (db_expr_t*) &ddb_regs.tf_scratch.gr30, FCN_NULL}, - {"r31", (db_expr_t*) &ddb_regs.tf_scratch.gr31, FCN_NULL}, - - /* Stacked registers */ - {"r32", (db_expr_t*) 32, db_get_rse_reg}, - {"r33", (db_expr_t*) 33, db_get_rse_reg}, - {"r34", (db_expr_t*) 34, db_get_rse_reg}, - {"r35", (db_expr_t*) 35, db_get_rse_reg}, - {"r36", (db_expr_t*) 36, db_get_rse_reg}, - {"r37", (db_expr_t*) 37, db_get_rse_reg}, - {"r38", (db_expr_t*) 38, db_get_rse_reg}, - {"r39", (db_expr_t*) 39, db_get_rse_reg}, - {"r40", (db_expr_t*) 40, db_get_rse_reg}, - {"r41", (db_expr_t*) 41, db_get_rse_reg}, - {"r42", (db_expr_t*) 42, db_get_rse_reg}, - {"r43", (db_expr_t*) 43, db_get_rse_reg}, - {"r44", (db_expr_t*) 44, db_get_rse_reg}, - {"r45", (db_expr_t*) 45, db_get_rse_reg}, - {"r46", (db_expr_t*) 46, db_get_rse_reg}, - {"r47", (db_expr_t*) 47, db_get_rse_reg}, - {"r48", (db_expr_t*) 48, db_get_rse_reg}, - {"r49", (db_expr_t*) 49, db_get_rse_reg}, - {"r50", (db_expr_t*) 50, db_get_rse_reg}, - {"r51", (db_expr_t*) 51, db_get_rse_reg}, - {"r52", (db_expr_t*) 52, db_get_rse_reg}, - {"r53", (db_expr_t*) 53, db_get_rse_reg}, - {"r54", (db_expr_t*) 54, db_get_rse_reg}, - {"r55", (db_expr_t*) 55, db_get_rse_reg}, - {"r56", (db_expr_t*) 56, db_get_rse_reg}, - {"r57", (db_expr_t*) 57, db_get_rse_reg}, - {"r58", (db_expr_t*) 58, db_get_rse_reg}, - {"r59", (db_expr_t*) 59, db_get_rse_reg}, - {"r60", (db_expr_t*) 60, db_get_rse_reg}, - {"r61", (db_expr_t*) 61, db_get_rse_reg}, - {"r62", (db_expr_t*) 62, db_get_rse_reg}, - {"r63", (db_expr_t*) 63, db_get_rse_reg}, - {"r64", (db_expr_t*) 64, db_get_rse_reg}, - {"r65", (db_expr_t*) 65, db_get_rse_reg}, - {"r66", (db_expr_t*) 66, db_get_rse_reg}, - {"r67", (db_expr_t*) 67, db_get_rse_reg}, - {"r68", (db_expr_t*) 68, db_get_rse_reg}, - {"r69", (db_expr_t*) 69, db_get_rse_reg}, - {"r70", (db_expr_t*) 70, db_get_rse_reg}, - {"r71", (db_expr_t*) 71, db_get_rse_reg}, - {"r72", (db_expr_t*) 72, db_get_rse_reg}, - {"r73", (db_expr_t*) 73, db_get_rse_reg}, - {"r74", (db_expr_t*) 74, db_get_rse_reg}, - {"r75", (db_expr_t*) 75, db_get_rse_reg}, - {"r76", (db_expr_t*) 76, db_get_rse_reg}, - {"r77", (db_expr_t*) 77, db_get_rse_reg}, - {"r78", (db_expr_t*) 78, db_get_rse_reg}, - {"r79", (db_expr_t*) 79, db_get_rse_reg}, - {"r80", (db_expr_t*) 80, db_get_rse_reg}, - {"r81", (db_expr_t*) 81, db_get_rse_reg}, - {"r82", (db_expr_t*) 82, db_get_rse_reg}, - {"r83", (db_expr_t*) 83, db_get_rse_reg}, - {"r84", (db_expr_t*) 84, db_get_rse_reg}, - {"r85", (db_expr_t*) 85, db_get_rse_reg}, - {"r86", (db_expr_t*) 86, db_get_rse_reg}, - {"r87", (db_expr_t*) 87, db_get_rse_reg}, - {"r88", (db_expr_t*) 88, db_get_rse_reg}, - {"r89", (db_expr_t*) 89, db_get_rse_reg}, - {"r90", (db_expr_t*) 90, db_get_rse_reg}, - {"r91", (db_expr_t*) 91, db_get_rse_reg}, - {"r92", (db_expr_t*) 92, db_get_rse_reg}, - {"r93", (db_expr_t*) 93, db_get_rse_reg}, - {"r94", (db_expr_t*) 94, db_get_rse_reg}, - {"r95", (db_expr_t*) 95, db_get_rse_reg}, - {"r96", (db_expr_t*) 96, db_get_rse_reg}, - {"r97", (db_expr_t*) 97, db_get_rse_reg}, - {"r98", (db_expr_t*) 98, db_get_rse_reg}, - {"r99", (db_expr_t*) 99, db_get_rse_reg}, - {"r100", (db_expr_t*) 100, db_get_rse_reg}, - {"r101", (db_expr_t*) 101, db_get_rse_reg}, - {"r102", (db_expr_t*) 102, db_get_rse_reg}, - {"r103", (db_expr_t*) 103, db_get_rse_reg}, - {"r104", (db_expr_t*) 104, db_get_rse_reg}, - {"r105", (db_expr_t*) 105, db_get_rse_reg}, - {"r106", (db_expr_t*) 106, db_get_rse_reg}, - {"r107", (db_expr_t*) 107, db_get_rse_reg}, - {"r108", (db_expr_t*) 108, db_get_rse_reg}, - {"r109", (db_expr_t*) 109, db_get_rse_reg}, - {"r110", (db_expr_t*) 110, db_get_rse_reg}, - {"r111", (db_expr_t*) 111, db_get_rse_reg}, - {"r112", (db_expr_t*) 112, db_get_rse_reg}, - {"r113", (db_expr_t*) 113, db_get_rse_reg}, - {"r114", (db_expr_t*) 114, db_get_rse_reg}, - {"r115", (db_expr_t*) 115, db_get_rse_reg}, - {"r116", (db_expr_t*) 116, db_get_rse_reg}, - {"r117", (db_expr_t*) 117, db_get_rse_reg}, - {"r118", (db_expr_t*) 118, db_get_rse_reg}, - {"r119", (db_expr_t*) 119, db_get_rse_reg}, - {"r120", (db_expr_t*) 120, db_get_rse_reg}, - {"r121", (db_expr_t*) 121, db_get_rse_reg}, - {"r122", (db_expr_t*) 122, db_get_rse_reg}, - {"r123", (db_expr_t*) 123, db_get_rse_reg}, - {"r124", (db_expr_t*) 124, db_get_rse_reg}, - {"r125", (db_expr_t*) 125, db_get_rse_reg}, - {"r126", (db_expr_t*) 126, db_get_rse_reg}, - {"r127", (db_expr_t*) 127, db_get_rse_reg}, + {"ip", NULL, db_getip}, + {"cr.ifs", DB_OFFSET(tf_special.cfm), db_frame}, + {"cr.ifa", DB_OFFSET(tf_special.ifa), db_frame}, + {"ar.bspstore", DB_OFFSET(tf_special.bspstore), db_frame}, + {"ndirty", DB_OFFSET(tf_special.ndirty), db_frame}, + {"rp", DB_OFFSET(tf_special.rp), db_frame}, + {"ar.pfs", DB_OFFSET(tf_special.pfs), db_frame}, + {"psr", DB_OFFSET(tf_special.psr), db_frame}, + {"cr.isr", DB_OFFSET(tf_special.isr), db_frame}, + {"pr", DB_OFFSET(tf_special.pr), db_frame}, + {"ar.rsc", DB_OFFSET(tf_special.rsc), db_frame}, + {"ar.rnat", DB_OFFSET(tf_special.rnat), db_frame}, + {"ar.unat", DB_OFFSET(tf_special.unat), db_frame}, + {"ar.fpsr", DB_OFFSET(tf_special.fpsr), db_frame}, + {"gp", DB_OFFSET(tf_special.gp), db_frame}, + {"sp", DB_OFFSET(tf_special.sp), db_frame}, + {"tp", DB_OFFSET(tf_special.tp), db_frame}, + {"b6", DB_OFFSET(tf_scratch.br6), db_frame}, + {"b7", DB_OFFSET(tf_scratch.br7), db_frame}, + {"r2", DB_OFFSET(tf_scratch.gr2), db_frame}, + {"r3", DB_OFFSET(tf_scratch.gr3), db_frame}, + {"r8", DB_OFFSET(tf_scratch.gr8), db_frame}, + {"r9", DB_OFFSET(tf_scratch.gr9), db_frame}, + {"r10", DB_OFFSET(tf_scratch.gr10), db_frame}, + {"r11", DB_OFFSET(tf_scratch.gr11), db_frame}, + {"r14", DB_OFFSET(tf_scratch.gr14), db_frame}, + {"r15", DB_OFFSET(tf_scratch.gr15), db_frame}, + {"r16", DB_OFFSET(tf_scratch.gr16), db_frame}, + {"r17", DB_OFFSET(tf_scratch.gr17), db_frame}, + {"r18", DB_OFFSET(tf_scratch.gr18), db_frame}, + {"r19", DB_OFFSET(tf_scratch.gr19), db_frame}, + {"r20", DB_OFFSET(tf_scratch.gr20), db_frame}, + {"r21", DB_OFFSET(tf_scratch.gr21), db_frame}, + {"r22", DB_OFFSET(tf_scratch.gr22), db_frame}, + {"r23", DB_OFFSET(tf_scratch.gr23), db_frame}, + {"r24", DB_OFFSET(tf_scratch.gr24), db_frame}, + {"r25", DB_OFFSET(tf_scratch.gr25), db_frame}, + {"r26", DB_OFFSET(tf_scratch.gr26), db_frame}, + {"r27", DB_OFFSET(tf_scratch.gr27), db_frame}, + {"r28", DB_OFFSET(tf_scratch.gr28), db_frame}, + {"r29", DB_OFFSET(tf_scratch.gr29), db_frame}, + {"r30", DB_OFFSET(tf_scratch.gr30), db_frame}, + {"r31", DB_OFFSET(tf_scratch.gr31), db_frame}, + {"r32", (db_expr_t*)0, db_getrse}, + {"r33", (db_expr_t*)1, db_getrse}, + {"r34", (db_expr_t*)2, db_getrse}, + {"r35", (db_expr_t*)3, db_getrse}, + {"r36", (db_expr_t*)4, db_getrse}, + {"r37", (db_expr_t*)5, db_getrse}, + {"r38", (db_expr_t*)6, db_getrse}, + {"r39", (db_expr_t*)7, db_getrse}, + {"r40", (db_expr_t*)8, db_getrse}, + {"r41", (db_expr_t*)9, db_getrse}, + {"r42", (db_expr_t*)10, db_getrse}, + {"r43", (db_expr_t*)11, db_getrse}, + {"r44", (db_expr_t*)12, db_getrse}, + {"r45", (db_expr_t*)13, db_getrse}, + {"r46", (db_expr_t*)14, db_getrse}, + {"r47", (db_expr_t*)15, db_getrse}, + {"r48", (db_expr_t*)16, db_getrse}, + {"r49", (db_expr_t*)17, db_getrse}, + {"r50", (db_expr_t*)18, db_getrse}, + {"r51", (db_expr_t*)19, db_getrse}, + {"r52", (db_expr_t*)20, db_getrse}, + {"r53", (db_expr_t*)21, db_getrse}, + {"r54", (db_expr_t*)22, db_getrse}, + {"r55", (db_expr_t*)23, db_getrse}, + {"r56", (db_expr_t*)24, db_getrse}, + {"r57", (db_expr_t*)25, db_getrse}, + {"r58", (db_expr_t*)26, db_getrse}, + {"r59", (db_expr_t*)27, db_getrse}, + {"r60", (db_expr_t*)28, db_getrse}, + {"r61", (db_expr_t*)29, db_getrse}, + {"r62", (db_expr_t*)30, db_getrse}, + {"r63", (db_expr_t*)31, db_getrse}, + {"r64", (db_expr_t*)32, db_getrse}, + {"r65", (db_expr_t*)33, db_getrse}, + {"r66", (db_expr_t*)34, db_getrse}, + {"r67", (db_expr_t*)35, db_getrse}, + {"r68", (db_expr_t*)36, db_getrse}, + {"r69", (db_expr_t*)37, db_getrse}, + {"r70", (db_expr_t*)38, db_getrse}, + {"r71", (db_expr_t*)39, db_getrse}, + {"r72", (db_expr_t*)40, db_getrse}, + {"r73", (db_expr_t*)41, db_getrse}, + {"r74", (db_expr_t*)42, db_getrse}, + {"r75", (db_expr_t*)43, db_getrse}, + {"r76", (db_expr_t*)44, db_getrse}, + {"r77", (db_expr_t*)45, db_getrse}, + {"r78", (db_expr_t*)46, db_getrse}, + {"r79", (db_expr_t*)47, db_getrse}, + {"r80", (db_expr_t*)48, db_getrse}, + {"r81", (db_expr_t*)49, db_getrse}, + {"r82", (db_expr_t*)50, db_getrse}, + {"r83", (db_expr_t*)51, db_getrse}, + {"r84", (db_expr_t*)52, db_getrse}, + {"r85", (db_expr_t*)53, db_getrse}, + {"r86", (db_expr_t*)54, db_getrse}, + {"r87", (db_expr_t*)55, db_getrse}, + {"r88", (db_expr_t*)56, db_getrse}, + {"r89", (db_expr_t*)57, db_getrse}, + {"r90", (db_expr_t*)58, db_getrse}, + {"r91", (db_expr_t*)59, db_getrse}, + {"r92", (db_expr_t*)60, db_getrse}, + {"r93", (db_expr_t*)61, db_getrse}, + {"r94", (db_expr_t*)62, db_getrse}, + {"r95", (db_expr_t*)63, db_getrse}, + {"r96", (db_expr_t*)64, db_getrse}, + {"r97", (db_expr_t*)65, db_getrse}, + {"r98", (db_expr_t*)66, db_getrse}, + {"r99", (db_expr_t*)67, db_getrse}, + {"r100", (db_expr_t*)68, db_getrse}, + {"r101", (db_expr_t*)69, db_getrse}, + {"r102", (db_expr_t*)70, db_getrse}, + {"r103", (db_expr_t*)71, db_getrse}, + {"r104", (db_expr_t*)72, db_getrse}, + {"r105", (db_expr_t*)73, db_getrse}, + {"r106", (db_expr_t*)74, db_getrse}, + {"r107", (db_expr_t*)75, db_getrse}, + {"r108", (db_expr_t*)76, db_getrse}, + {"r109", (db_expr_t*)77, db_getrse}, + {"r110", (db_expr_t*)78, db_getrse}, + {"r111", (db_expr_t*)79, db_getrse}, + {"r112", (db_expr_t*)80, db_getrse}, + {"r113", (db_expr_t*)81, db_getrse}, + {"r114", (db_expr_t*)82, db_getrse}, + {"r115", (db_expr_t*)83, db_getrse}, + {"r116", (db_expr_t*)84, db_getrse}, + {"r117", (db_expr_t*)85, db_getrse}, + {"r118", (db_expr_t*)86, db_getrse}, + {"r119", (db_expr_t*)87, db_getrse}, + {"r120", (db_expr_t*)88, db_getrse}, + {"r121", (db_expr_t*)89, db_getrse}, + {"r122", (db_expr_t*)90, db_getrse}, + {"r123", (db_expr_t*)91, db_getrse}, + {"r124", (db_expr_t*)92, db_getrse}, + {"r125", (db_expr_t*)93, db_getrse}, + {"r126", (db_expr_t*)94, db_getrse}, + {"r127", (db_expr_t*)95, db_getrse}, }; struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); static int -db_get_rse_reg(struct db_variable *vp, db_expr_t *valuep, int op) +db_frame(struct db_variable *vp, db_expr_t *valuep, int op) { + uint64_t *reg; + + if (kdb_frame == NULL) + return (0); + reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep); + if (op == DB_VAR_GET) + *valuep = *reg; + else + *reg = *valuep; + return (1); +} + +static int +db_getrse(struct db_variable *vp, db_expr_t *valuep, int op) +{ u_int64_t *reg; uint64_t bsp; int nats, regno, sof; - bsp = ddb_regs.tf_special.bspstore + ddb_regs.tf_special.ndirty; - regno = (db_expr_t)vp->valuep - 32; - sof = (int)(ddb_regs.tf_special.cfm & 0x7f); - nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63; + if (kdb_frame == NULL) + return (0); - reg = (void*)(bsp - ((sof - regno + nats) << 3)); + regno = (int)(intptr_t)valuep; + bsp = kdb_frame->tf_special.bspstore + kdb_frame->tf_special.ndirty; + sof = (int)(kdb_frame->tf_special.cfm & 0x7f); - if (regno < sof) { - if (op == DB_VAR_GET) - *valuep = *reg; - else - *reg = *valuep; - } else { - if (op == DB_VAR_GET) - *valuep = 0xdeadbeefdeadbeef; - } + if (regno >= sof) + return (0); - return (0); + nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63; + reg = (void*)(bsp - ((sof - regno + nats) << 3)); + if (op == DB_VAR_GET) + *valuep = *reg; + else + *reg = *valuep; + return (1); } static int -db_get_ip_reg(struct db_variable *vp, db_expr_t *valuep, int op) +db_getip(struct db_variable *vp, db_expr_t *valuep, int op) { - /* Read only */ - if (op == DB_VAR_GET) - *valuep = PC_REGS(DDB_REGS); - return 0; -} + u_long iip, slot; -#if 0 -/* - * Print trap reason. - */ -static void -ddbprinttrap(int vector) -{ + if (kdb_frame == NULL) + return (0); - /* XXX Implement. */ - - printf("ddbprinttrap(%d)\n", vector); -} -#endif - -#define CPUSTOP_ON_DDBBREAK -#define VERBOSE_CPUSTOP_ON_DDBBREAK - -/* - * ddb_trap - field a kernel trap - */ -int -kdb_trap(int vector, struct trapframe *regs) -{ - int ddb_mode = !(boothowto & RB_GDB); - register_t s; - - /* - * Don't bother checking for usermode, since a benign entry - * by the kernel (call to Debugger() or a breakpoint) has - * already checked for usermode. If neither of those - * conditions exist, something Bad has happened. - */ - - if (vector != IA64_VEC_BREAK - && vector != IA64_VEC_SINGLE_STEP_TRAP) { -#if 0 - if (ddb_mode) { - db_printf("ddbprinttrap from 0x%lx\n", /* XXX */ - regs->tf_regs[FRAME_PC]); - ddbprinttrap(a0, a1, a2, entry); - /* - * Tell caller "We did NOT handle the trap." - * Caller should panic, or whatever. - */ + if (op == DB_VAR_GET) { + iip = kdb_frame->tf_special.iip; + slot = (kdb_frame->tf_special.psr >> 41) & 3; + *valuep = iip + slot; + } else { + iip = *valuep & ~0xf; + slot = *valuep & 0xf; + if (slot > 2) return (0); - } -#endif - if (db_nofault) { - jmp_buf *no_fault = db_nofault; - db_nofault = 0; - longjmp(*no_fault, 1); - } + kdb_frame->tf_special.iip = iip; + kdb_frame->tf_special.psr &= ~IA64_PSR_RI; + kdb_frame->tf_special.psr |= slot << 41; } - - /* - * XXX Should switch to DDB's own stack, here. - */ - - s = intr_disable(); - -#ifdef SMP -#ifdef CPUSTOP_ON_DDBBREAK - -#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf("CPU%d stopping CPUs: 0x%08x...", PCPU_GET(cpuid), - PCPU_GET(other_cpus)); -#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ - - /* We stop all CPUs except ourselves (obviously) */ - stop_cpus(PCPU_GET(other_cpus)); - -#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf(" stopped.\n"); -#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ - -#endif /* CPUSTOP_ON_DDBBREAK */ -#endif /* SMP */ - - ddb_regs = *regs; - - /* - * XXX pretend that registers outside the current frame don't exist. - */ - db_eregs = db_regs + DB_MISC_REGS + 3 + 27 + - (ddb_regs.tf_special.cfm & 0x7f); - - __asm __volatile("flushrs"); /* so we can look at them */ - - db_active++; - - if (ddb_mode) { - cndbctl(TRUE); /* DDB active, unblank video */ - db_trap(vector, 0); /* Where the work happens */ - cndbctl(FALSE); /* DDB inactive */ - } else - gdb_handle_exception(&ddb_regs, vector); - - db_active--; - -#ifdef SMP -#ifdef CPUSTOP_ON_DDBBREAK - -#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf("CPU%d restarting CPUs: 0x%08x...", PCPU_GET(cpuid), - stopped_cpus); -#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ - - /* Restart all the CPUs we previously stopped */ - if (stopped_cpus != PCPU_GET(other_cpus) && smp_started != 0) { - db_printf("whoa, other_cpus: 0x%08x, stopped_cpus: 0x%08x\n", - PCPU_GET(other_cpus), stopped_cpus); - panic("stop_cpus() failed"); - } - restart_cpus(stopped_cpus); - -#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf(" restarted.\n"); -#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ - -#endif /* CPUSTOP_ON_DDBBREAK */ -#endif /* SMP */ - - *regs = ddb_regs; - - intr_restore(s); - - - /* - * Tell caller "We HAVE handled the trap." - */ return (1); } /* * Read bytes from kernel address space for debugger. */ -void +int db_read_bytes(vm_offset_t addr, size_t size, char *data) { + jmp_buf jb; + void *prev_jb; + char *src; + int ret; - db_nofault = &db_jmpbuf; - - if (addr < VM_MAX_ADDRESS) - copyin((char *)addr, data, size); - else - bcopy((char *)addr, data, size); - - db_nofault = 0; + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + src = (char *)addr; + while (size-- > 0) + *data++ = *src++; + } + (void)kdb_jmpbuf(prev_jb); + return (ret); } /* * Write bytes to kernel address space for debugger. */ -void +int db_write_bytes(vm_offset_t addr, size_t size, char *data) { + jmp_buf jb; + void *prev_jb; + char *dst; + int ret; - db_nofault = &db_jmpbuf; - - if (addr < VM_MAX_ADDRESS) - copyout(data, (char *)addr, size); - else - bcopy(data, (char *)addr, size); - - db_nofault = 0; + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + dst = (char *)addr; + while (size-- > 0) + *dst++ = *data++; + } + (void)kdb_jmpbuf(prev_jb); + return (ret); } void -Debugger(const char* msg) +db_bkpt_write(db_addr_t addr, BKPT_INST_TYPE *storage) { - printf("%s\n", msg); - __asm("break 0x80100"); -} + BKPT_INST_TYPE tmp; + db_addr_t loc; + int slot; -u_long -db_register_value(db_regs_t *regs, int regno) -{ - uint64_t *rsp; - uint64_t bsp; - int nats, sof; + slot = addr & 0xfUL; + if (slot >= SLOT_COUNT) + return; + loc = (addr & ~0xfUL) + (slot << 2); - if (regno == 0) - return (0); - if (regno == 1) - return (regs->tf_special.gp); - if (regno >= 2 && regno <= 3) - return ((®s->tf_scratch.gr2)[regno - 2]); - if (regno >= 8 && regno <= 11) - return ((®s->tf_scratch.gr8)[regno - 8]); - if (regno == 12) - return (regs->tf_special.sp); - if (regno == 13) - return (regs->tf_special.tp); - if (regno >= 14 && regno <= 31) - return ((®s->tf_scratch.gr14)[regno - 14]); + db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp); + *storage = (tmp >> SLOT_SHIFT(slot)) & SLOT_MASK; - sof = (int)(regs->tf_special.cfm & 0x7f); - if (regno >= 32 && regno < sof + 32) { - bsp = regs->tf_special.bspstore + regs->tf_special.ndirty; - regno -= 32; - nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63; - rsp = (void*)(bsp - ((sof - regno + nats) << 3)); - return (*rsp); - } - - db_printf(" **** STRANGE REGISTER NUMBER %d **** ", regno); - return (0); + tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot)); + tmp |= (0x84000 << 6) << SLOT_SHIFT(slot); + db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp); } void -db_write_breakpoint(vm_offset_t addr, u_int64_t *storage) +db_bkpt_clear(db_addr_t addr, BKPT_INST_TYPE *storage) { -} + BKPT_INST_TYPE tmp; + db_addr_t loc; + int slot; -void -db_clear_breakpoint(vm_offset_t addr, u_int64_t *storage) -{ + slot = addr & 0xfUL; + if (slot >= SLOT_COUNT) + return; + loc = (addr & ~0xfUL) + (slot << 2); + + db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp); + tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot)); + tmp |= *storage << SLOT_SHIFT(slot); + db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp); } void -db_skip_breakpoint() +db_bkpt_skip(void) { - ddb_regs.tf_special.psr += IA64_PSR_RI_1; - if ((ddb_regs.tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) { - ddb_regs.tf_special.psr &= ~IA64_PSR_RI; - ddb_regs.tf_special.iip += 16; + if (kdb_frame == NULL) + return; + + kdb_frame->tf_special.psr += IA64_PSR_RI_1; + if ((kdb_frame->tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) { + kdb_frame->tf_special.psr &= ~IA64_PSR_RI; + kdb_frame->tf_special.iip += 16; } } db_addr_t db_disasm(db_addr_t loc, boolean_t altfmt) { char buf[32]; struct asm_bundle bundle; const struct asm_inst *i; const char *tmpl; int n, slot; slot = loc & 0xf; loc &= ~0xful; db_read_bytes(loc, 16, buf); if (asm_decode((uintptr_t)buf, &bundle)) { i = bundle.b_inst + slot; tmpl = bundle.b_templ + slot; if (*tmpl == ';' || (slot == 2 && bundle.b_templ[1] == ';')) tmpl++; if (*tmpl == 'L' || i->i_op == ASM_OP_NONE) { db_printf("\n"); goto out; } /* Unit + slot. */ db_printf("[%c%d] ", *tmpl, slot); /* Predicate. */ if (i->i_oper[0].o_value != 0) { asm_operand(i->i_oper+0, buf, loc); db_printf("(%s) ", buf); } else db_printf(" "); /* Mnemonic & completers. */ asm_mnemonic(i->i_op, buf); db_printf(buf); n = 0; while (n < i->i_ncmpltrs) { asm_completer(i->i_cmpltr + n, buf); db_printf(buf); n++; } db_printf(" "); /* Operands. */ n = 1; while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) { if (n > 1) { if (n == i->i_srcidx) db_printf("="); else db_printf(","); } asm_operand(i->i_oper + n, buf, loc); db_printf(buf); n++; } } else { tmpl = NULL; slot = 2; } db_printf("\n"); out: slot++; if (slot == 1 && tmpl[1] == 'L') slot++; if (slot > 2) slot = 16; return (loc + slot); } void db_show_mdpcpu(struct pcpu *pc) { } Index: head/sys/ia64/ia64/db_trace.c =================================================================== --- head/sys/ia64/ia64/db_trace.c (revision 131951) +++ head/sys/ia64/ia64/db_trace.c (revision 131952) @@ -1,151 +1,181 @@ /*- + * Copyright (c) 2003, 2004 Marcel Moolenaar * Copyright (c) 2000-2001 Doug Rabson * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. * * $FreeBSD$ */ #include +#include #include + #include +#include +#include +#include #include #include #include #include #include #include #include - int db_md_set_watchpoint(db_expr_t addr, db_expr_t size); int db_md_clr_watchpoint(db_expr_t addr, db_expr_t size); void db_md_list_watchpoints(void); -void -db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, - char *modif) +static int +db_backtrace(struct thread *td, struct pcb *pcb, int count) { struct unw_regstate rs; struct trapframe *tf; const char *name; db_expr_t offset; uint64_t bsp, cfm, ip, pfs, reg, sp; c_db_sym_t sym; int args, error, i; - tf = &ddb_regs; - error = unw_create(&rs, tf); + error = unw_create_from_pcb(&rs, pcb); while (!error && count--) { error = unw_get_cfm(&rs, &cfm); if (!error) error = unw_get_bsp(&rs, &bsp); if (!error) error = unw_get_ip(&rs, &ip); if (!error) error = unw_get_sp(&rs, &sp); if (error) break; - args = (cfm >> 7) & 0x7f; + args = IA64_CFM_SOL(cfm); if (args > 8) args = 8; error = unw_step(&rs); if (!error) { - error = unw_get_cfm(&rs, &pfs); - if (!error) { - i = (pfs & 0x7f) - ((pfs >> 7) & 0x7f); + if (!unw_get_cfm(&rs, &pfs)) { + i = IA64_CFM_SOF(pfs) - IA64_CFM_SOL(pfs); if (args > i) args = i; } } sym = db_search_symbol(ip, DB_STGY_ANY, &offset); db_symbol_values(sym, &name, NULL); db_printf("%s(", name); if (bsp >= IA64_RR_BASE(5)) { for (i = 0; i < args; i++) { if ((bsp & 0x1ff) == 0x1f8) bsp += 8; db_read_bytes(bsp, sizeof(reg), (void*)®); if (i > 0) db_printf(", "); db_printf("0x%lx", reg); bsp += 8; } } else db_printf("..."); db_printf(") at "); db_printsym(ip, DB_STGY_PROC); db_printf("\n"); if (error != EOVERFLOW) continue; if (sp < IA64_RR_BASE(5)) break; tf = (struct trapframe *)(sp + 16); if ((tf->tf_flags & FRAME_SYSCALL) != 0 || tf->tf_special.iip < IA64_RR_BASE(5)) break; /* XXX ask if we should unwind across the trapframe. */ db_printf("--- trapframe at %p\n", tf); unw_delete(&rs); - error = unw_create(&rs, tf); + error = unw_create_from_frame(&rs, tf); } unw_delete(&rs); + return (error); } void -db_print_backtrace(void) +db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, + char *modif) { + struct thread *td; + + td = (have_addr) ? kdb_thr_lookup(addr) : kdb_thread; + if (td == NULL) { + db_printf("Thread %d not found\n", (int)addr); + return; + } + db_trace_thread(td, count); +} + +void +db_trace_self(void) +{ + struct pcb pcb; + + savectx(&pcb); + db_backtrace(curthread, &pcb, -1); +} + +int +db_trace_thread(struct thread *td, int count) +{ + struct pcb *ctx; + + ctx = kdb_thr_ctx(td); + return (db_backtrace(td, ctx, count)); } int db_md_set_watchpoint(addr, size) db_expr_t addr; db_expr_t size; { return (-1); } int db_md_clr_watchpoint(addr, size) db_expr_t addr; db_expr_t size; { return (-1); } void db_md_list_watchpoints() { return; } Index: head/sys/ia64/include/db_machdep.h =================================================================== --- head/sys/ia64/include/db_machdep.h (revision 131951) +++ head/sys/ia64/include/db_machdep.h (revision 131952) @@ -1,114 +1,76 @@ -/* $FreeBSD$ */ -/* $NetBSD: db_machdep.h,v 1.6 1997/09/06 02:02:25 thorpej Exp $ */ - /* - * Copyright (c) 1995 Carnegie-Mellon University. + * Copyright (c) 2004 Marcel Moolenaar * All rights reserved. * - * Author: Chris G. Demetriou + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * 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. + * 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. * - * 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. + * 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. * - * 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 the - * rights to redistribute these changes. + * $FreeBSD$ */ #ifndef _MACHINE_DB_MACHDEP_H_ #define _MACHINE_DB_MACHDEP_H_ -/* - * Machine-dependent defines for new kernel debugger. - */ - -#include -#include -#include #include -#define DB_NO_AOUT +/* We define some of our own commands. */ +#define DB_MACHINE_COMMANDS -struct ia64_bundle; +/* We use Elf64 symbols in DDB. */ +#define DB_ELFSIZE 64 +/* Pretty arbitrary. */ +#define DB_SMALL_VALUE_MAX 0x7fffffff +#define DB_SMALL_VALUE_MIN (-0x400001) + typedef vm_offset_t db_addr_t; /* address - unsigned */ typedef long db_expr_t; /* expression - signed */ -typedef struct trapframe db_regs_t; -extern db_regs_t ddb_regs; /* register state */ -#define DDB_REGS (&ddb_regs) -#define PC_REGS(regs) ((db_addr_t)(regs)->tf_special.iip + \ - (((regs)->tf_special.psr >> 41) & 3)) +#define PC_REGS() ((kdb_thrctx->pcb_special.__spare == 0) ? \ + kdb_thrctx->pcb_special.rp : \ + kdb_thrctx->pcb_special.iip + ((kdb_thrctx->pcb_special.psr>>41) & 3)) -#define BKPT_WRITE(addr, storage) db_write_breakpoint(addr, storage) -#define BKPT_CLEAR(addr, storage) db_clear_breakpoint(addr, storage) -#define BKPT_INST_TYPE u_int64_t +#define BKPT_WRITE(addr, storage) db_bkpt_write(addr, storage) +#define BKPT_CLEAR(addr, storage) db_bkpt_clear(addr, storage) +#define BKPT_SKIP db_bkpt_skip() +#define BKPT_INST_TYPE uint64_t -#define BKPT_SKIP db_skip_breakpoint() +void db_bkpt_write(db_addr_t, BKPT_INST_TYPE *storage); +void db_bkpt_clear(db_addr_t, uint64_t *storage); +void db_bkpt_skip(void); -#define db_clear_single_step(regs) ddb_regs.tf_special.psr &= ~IA64_PSR_SS -#define db_set_single_step(regs) ddb_regs.tf_special.psr |= IA64_PSR_SS +#define db_clear_single_step kdb_cpu_clear_singlestep +#define db_set_single_step kdb_cpu_set_singlestep #define IS_BREAKPOINT_TRAP(type, code) (type == IA64_VEC_BREAK) #define IS_WATCHPOINT_TRAP(type, code) 0 #define inst_trap_return(ins) (ins & 0) #define inst_return(ins) (ins & 0) #define inst_call(ins) (ins & 0) #define inst_branch(ins) (ins & 0) #define inst_load(ins) (ins & 0) #define inst_store(ins) (ins & 0) #define inst_unconditional_flow_transfer(ins) (ins & 0) - -#define branch_taken(ins, pc, regs) pc -/* - * Functions needed for software single-stepping. - */ - -/* No delay slots on Alpha. */ -#define next_instr_address(v, b) ((db_addr_t) ((b) ? (v) : ((v) + 4))) - -u_long db_register_value(db_regs_t *, int); -int kdb_trap(int vector, struct trapframe *regs); - -u_int64_t *db_rse_current_frame(void); -u_int64_t *db_rse_previous_frame(u_int64_t *bsp, int sof); -u_int64_t *db_rse_register_address(u_int64_t *bsp, int regno); - -void db_read_bundle(db_addr_t addr, struct ia64_bundle *bp); -void db_write_bundle(db_addr_t addr, struct ia64_bundle *bp); -void db_write_breakpoint(db_addr_t addr, u_int64_t *storage); -void db_clear_breakpoint(db_addr_t addr, u_int64_t *storage); -void db_skip_breakpoint(void); - -/* - * Pretty arbitrary - */ -#define DB_SMALL_VALUE_MAX 0x7fffffff -#define DB_SMALL_VALUE_MIN (-0x400001) - -/* - * We define some of our own commands. - */ -#define DB_MACHINE_COMMANDS - -/* - * We use Elf64 symbols in DDB. - */ -#define DB_ELFSIZE 64 +#define branch_taken(ins, pc, regs) pc #endif /* _MACHINE_DB_MACHDEP_H_ */ Index: head/sys/sparc64/include/db_machdep.h =================================================================== --- head/sys/sparc64/include/db_machdep.h (revision 131951) +++ head/sys/sparc64/include/db_machdep.h (revision 131952) @@ -1,73 +1,69 @@ /* * Mach Operating System * Copyright (c) 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. * * from: FreeBSD: src/sys/i386/include/db_machdep.h,v 1.16 1999/10/04 * $FreeBSD$ */ #ifndef _MACHINE_DB_MACHDEP_H_ #define _MACHINE_DB_MACHDEP_H_ #include #include #define BYTE_MSF (1) typedef vm_offset_t db_addr_t; typedef long db_expr_t; -typedef struct trapframe db_regs_t; -extern db_regs_t ddb_regs; -#define DDB_REGS (&ddb_regs) +#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_pc) -#define PC_REGS(regs) ((db_addr_t)(regs)->tf_tpc) - #define BKPT_INST (0x91d03001) #define BKPT_SIZE (4) #define BKPT_SET(inst) (BKPT_INST) #define BKPT_SKIP do { \ - ddb_regs.tf_tpc = ddb_regs.tf_tnpc + 4; \ - ddb_regs.tf_tnpc += 8; \ + kdb_frame->tf_tpc = kdb_frame->tf_tnpc + 4; \ + kdb_frame->tf_tnpc += 8; \ } while (0) -#define db_clear_single_step(regs) -#define db_set_single_step(regs) +#define db_clear_single_step kdb_cpu_clear_singlestep +#define db_set_single_step kdb_cpu_set_singlestep #define IS_BREAKPOINT_TRAP(type, code) (type == T_BREAKPOINT) #define IS_WATCHPOINT_TRAP(type, code) (0) #define inst_trap_return(ins) (0) #define inst_return(ins) (0) #define inst_call(ins) (0) #define inst_load(ins) (0) #define inst_store(ins) (0) #define DB_SMALL_VALUE_MAX (0x7fffffff) #define DB_SMALL_VALUE_MIN (-0x40001) #define DB_ELFSIZE 64 #endif /* !_MACHINE_DB_MACHDEP_H_ */ Index: head/sys/sparc64/sparc64/db_interface.c =================================================================== --- head/sys/sparc64/sparc64/db_interface.c (revision 131951) +++ head/sys/sparc64/sparc64/db_interface.c (revision 131952) @@ -1,129 +1,106 @@ /*- * Copyright (c) 2001 Jake Burkholder. * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. * * $FreeBSD$ */ #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -static jmp_buf *db_nofault = 0; -extern jmp_buf db_jmpbuf; - -int db_active; -db_regs_t ddb_regs; - -static jmp_buf db_global_jmpbuf; -static int db_global_jmpbuf_valid; - int -kdb_trap(struct trapframe *tf) -{ - - if (db_global_jmpbuf_valid) - longjmp(db_global_jmpbuf, 1); - flushw(); - ddb_regs = *tf; - critical_enter(); - setjmp(db_global_jmpbuf); - db_global_jmpbuf_valid = TRUE; - atomic_add_acq_int(&db_active, 1); -#ifdef SMP - stop_cpus(PCPU_GET(other_cpus)); -#endif - cndbctl(TRUE); - db_trap(tf->tf_type, 0); - cndbctl(FALSE); - db_active--; -#ifdef SMP - restart_cpus(stopped_cpus); -#endif - db_global_jmpbuf_valid = FALSE; - critical_exit(); - *tf = ddb_regs; - TF_DONE(tf); - return (1); -} - -void db_read_bytes(vm_offset_t addr, size_t size, char *data) { + jmp_buf jb; + void *prev_jb; char *src; + int ret; - db_nofault = &db_jmpbuf; - src = (char *)addr; - while (size-- > 0) - *data++ = *src++; - db_nofault = NULL; + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + src = (char *)addr; + while (size-- > 0) + *data++ = *src++; + } + (void)kdb_jmpbuf(prev_jb); + return (ret); } -void +int db_write_bytes(vm_offset_t addr, size_t size, char *data) { + jmp_buf jb; + void *prev_jb; char *dst; + int ret; - db_nofault = &db_jmpbuf; - dst = (char *)addr; - while (size-- > 0) - *dst++ = *data++; - db_nofault = NULL; + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + dst = (char *)addr; + while (size-- > 0) + *dst++ = *data++; + } + (void)kdb_jmpbuf(prev_jb); + return (ret); } void db_show_mdpcpu(struct pcpu *pc) { } DB_COMMAND(reboot, db_reboot) { cpu_reset(); } DB_COMMAND(halt, db_halt) { cpu_halt(); } Index: head/sys/sparc64/sparc64/db_trace.c =================================================================== --- head/sys/sparc64/sparc64/db_trace.c (revision 131951) +++ head/sys/sparc64/sparc64/db_trace.c (revision 131952) @@ -1,316 +1,304 @@ /*- * Copyright (c) 2001 Jake Burkholder. * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. * * $FreeBSD$ */ #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -static int db_print_trap(struct thread *td, struct trapframe *); -static void db_utrace(struct thread *td, struct trapframe *tf); - #define INKERNEL(va) \ ((va) >= VM_MIN_KERNEL_ADDRESS && (va) <= VM_MAX_KERNEL_ADDRESS) +static db_varfcn_t db_frame; + +#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) struct db_variable db_regs[] = { - { "g0", &ddb_regs.tf_global[0], FCN_NULL }, - { "g1", &ddb_regs.tf_global[1], FCN_NULL }, - { "g2", &ddb_regs.tf_global[2], FCN_NULL }, - { "g3", &ddb_regs.tf_global[3], FCN_NULL }, - { "g4", &ddb_regs.tf_global[4], FCN_NULL }, - { "g5", &ddb_regs.tf_global[5], FCN_NULL }, - { "g6", &ddb_regs.tf_global[6], FCN_NULL }, - { "g7", &ddb_regs.tf_global[7], FCN_NULL }, - { "i0", &ddb_regs.tf_out[0], FCN_NULL }, - { "i1", &ddb_regs.tf_out[1], FCN_NULL }, - { "i2", &ddb_regs.tf_out[2], FCN_NULL }, - { "i3", &ddb_regs.tf_out[3], FCN_NULL }, - { "i4", &ddb_regs.tf_out[4], FCN_NULL }, - { "i5", &ddb_regs.tf_out[5], FCN_NULL }, - { "i6", &ddb_regs.tf_out[6], FCN_NULL }, - { "i7", &ddb_regs.tf_out[7], FCN_NULL }, - { "tnpc", &ddb_regs.tf_tnpc, FCN_NULL }, - { "tpc", &ddb_regs.tf_tpc, FCN_NULL }, - { "tstate", &ddb_regs.tf_tstate, FCN_NULL }, + { "g0", DB_OFFSET(tf_global[0]), db_frame }, + { "g1", DB_OFFSET(tf_global[1]), db_frame }, + { "g2", DB_OFFSET(tf_global[2]), db_frame }, + { "g3", DB_OFFSET(tf_global[3]), db_frame }, + { "g4", DB_OFFSET(tf_global[4]), db_frame }, + { "g5", DB_OFFSET(tf_global[5]), db_frame }, + { "g6", DB_OFFSET(tf_global[6]), db_frame }, + { "g7", DB_OFFSET(tf_global[7]), db_frame }, + { "i0", DB_OFFSET(tf_out[0]), db_frame }, + { "i1", DB_OFFSET(tf_out[1]), db_frame }, + { "i2", DB_OFFSET(tf_out[2]), db_frame }, + { "i3", DB_OFFSET(tf_out[3]), db_frame }, + { "i4", DB_OFFSET(tf_out[4]), db_frame }, + { "i5", DB_OFFSET(tf_out[5]), db_frame }, + { "i6", DB_OFFSET(tf_out[6]), db_frame }, + { "i7", DB_OFFSET(tf_out[7]), db_frame }, + { "tnpc", DB_OFFSET(tf_tnpc), db_frame }, + { "tpc", DB_OFFSET(tf_tpc), db_frame }, + { "tstate", DB_OFFSET(tf_tstate), db_frame }, }; struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); -void -db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, - char *modif) +static int +db_frame(struct db_variable *vp, db_expr_t *valuep, int op) { - struct trapframe *tf; - struct frame *fp; - struct proc *p; - struct thread *td; - const char *name; - c_db_sym_t sym; - db_expr_t offset; - db_expr_t value; - db_addr_t npc; - db_addr_t pc; - int trap; - int user; - pid_t pid; + uint64_t *reg; - trap = 0; - user = 0; - npc = 0; - if (count == -1) - count = 1024; - td = curthread; - p = td->td_proc; - /* - * Provide an /a modifier to pass the stack address instead of a PID - * as argument. - * Note that, if this address is not on the stack of curthread, the - * printed data may be wrong (at the moment, this applies only to the - * sysent list). - */ - if (!have_addr) - addr = DDB_REGS->tf_out[6]; - else if (strcmp(modif, "a") != 0) { - /* - * addr was parsed as hex, convert so it is interpreted as - * decimal (ugh). - */ - pid = (addr % 16) + ((addr >> 4) % 16) * 10 + - ((addr >> 8) % 16) * 100 + ((addr >> 12) % 16) * 1000 + - ((addr >> 16) % 16) * 10000; - /* - * The pcb for curproc is not valid at this point, - * so fall back to the default case. - */ - if (pid == curthread->td_proc->p_pid) { - td = curthread; - p = td->td_proc; - addr = DDB_REGS->tf_out[6]; - } else { - /* sx_slock(&allproc_lock); */ - LIST_FOREACH(p, &allproc, p_list) { - if (p->p_pid == pid) - break; + if (kdb_frame == NULL) + return (0); + reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep); + if (op == DB_VAR_GET) + *valuep = *reg; + else + *reg = *valuep; + return (1); +} + +/* + * User stack trace (debugging aid). + */ +static void +db_utrace(struct thread *td, struct trapframe *tf) +{ + struct pcb *pcb; + db_addr_t sp, rsp, o7, pc; + int i, found; + + pcb = td->td_pcb; + sp = db_get_value((db_addr_t)&tf->tf_sp, sizeof(tf->tf_sp), FALSE); + o7 = db_get_value((db_addr_t)&tf->tf_out[7], sizeof(tf->tf_out[7]), + FALSE); + pc = db_get_value((db_addr_t)&tf->tf_tpc, sizeof(tf->tf_tpc), FALSE); + db_printf("user trace: trap %%o7=%#lx\n", o7); + while (sp != 0) { + db_printf("pc %#lx, sp %#lx\n", pc, sp); + /* First, check whether the frame is in the pcb. */ + found = 0; + for (i = 0; i < pcb->pcb_nsaved; i++) { + if (pcb->pcb_rwsp[i] == sp) { + found = 1; + sp = pcb->pcb_rw[i].rw_in[6]; + pc = pcb->pcb_rw[i].rw_in[7]; + break; } - /* sx_sunlock(&allproc_lock); */ - if (p == NULL) { - db_printf("pid %d not found\n", pid); - return; - } - if ((p->p_sflag & PS_INMEM) == 0) { - db_printf("pid %d swapped out\n", pid); - return; - } - td = FIRST_THREAD_IN_PROC(p); /* XXXKSE */ - addr = td->td_pcb->pcb_sp; } - } - fp = (struct frame *)(addr + SPOFF); - - while (count-- && !user) { - pc = (db_addr_t)db_get_value((db_addr_t)&fp->fr_pc, - sizeof(fp->fr_pc), FALSE); - if (trap) { - pc = npc; - trap = 0; + if (!found) { + rsp = sp + SPOFF; + sp = 0; + if (copyin((void *)(rsp + offsetof(struct frame, fr_fp)), + &sp, sizeof(sp)) != 0 || + copyin((void *)(rsp + offsetof(struct frame, fr_pc)), + &pc, sizeof(pc)) != 0) + break; } - if (!INKERNEL((vm_offset_t)pc)) - break; - sym = db_search_symbol(pc, DB_STGY_ANY, &offset); - if (sym == C_DB_SYM_NULL) { - value = 0; - name = NULL; - } else - db_symbol_values(sym, &name, &value); - if (name == NULL) - name = "(null)"; - fp = (struct frame *)(db_get_value((db_addr_t)&fp->fr_fp, - sizeof(fp->fr_fp), FALSE) + SPOFF); - if (bcmp(name, "tl0_", 4) == 0 || - bcmp(name, "tl1_", 4) == 0) { - tf = (struct trapframe *)(fp + 1); - npc = db_get_value((db_addr_t)&tf->tf_tpc, - sizeof(tf->tf_tpc), FALSE); - user = db_print_trap(td, tf); - trap = 1; - } else { - db_printf("%s() at ", name); - db_printsym(pc, DB_STGY_PROC); - db_printf("\n"); - } } + db_printf("done\n"); } static int db_print_trap(struct thread *td, struct trapframe *tf) { struct proc *p; const char *symname; c_db_sym_t sym; db_expr_t diff; db_addr_t func; db_addr_t tpc; u_long type; u_long sfar; u_long sfsr; u_long tar; u_long level; u_long pil; u_long code; u_long o7; int user; p = td->td_proc; type = db_get_value((db_addr_t)&tf->tf_type, sizeof(tf->tf_type), FALSE); db_printf("-- %s", trap_msg[type & ~T_KERNEL]); switch (type & ~T_KERNEL) { case T_DATA_PROTECTION: tar = (u_long)db_get_value((db_addr_t)&tf->tf_tar, sizeof(tf->tf_tar), FALSE); db_printf(" tar=%#lx", tar); /* fall through */ case T_DATA_EXCEPTION: case T_INSTRUCTION_EXCEPTION: case T_MEM_ADDRESS_NOT_ALIGNED: sfar = (u_long)db_get_value((db_addr_t)&tf->tf_sfar, sizeof(tf->tf_sfar), FALSE); sfsr = (u_long)db_get_value((db_addr_t)&tf->tf_sfsr, sizeof(tf->tf_sfsr), FALSE); db_printf(" sfar=%#lx sfsr=%#lx", sfar, sfsr); break; case T_DATA_MISS: case T_INSTRUCTION_MISS: tar = (u_long)db_get_value((db_addr_t)&tf->tf_tar, sizeof(tf->tf_tar), FALSE); db_printf(" tar=%#lx", tar); break; case T_SYSCALL: code = db_get_value((db_addr_t)&tf->tf_global[1], sizeof(tf->tf_global[1]), FALSE); db_printf(" (%ld", code); if (code >= 0 && code < p->p_sysent->sv_size) { func = (db_addr_t)p->p_sysent->sv_table[code].sy_call; sym = db_search_symbol(func, DB_STGY_ANY, &diff); if (sym != DB_SYM_NULL && diff == 0) { db_symbol_values(sym, &symname, NULL); db_printf(", %s, %s", p->p_sysent->sv_name, symname); } db_printf(")"); } break; case T_INTERRUPT: level = (u_long)db_get_value((db_addr_t)&tf->tf_level, sizeof(tf->tf_level), FALSE); pil = (u_long)db_get_value((db_addr_t)&tf->tf_pil, sizeof(tf->tf_pil), FALSE); db_printf(" level=%#lx pil=%#lx", level, pil); break; default: break; } o7 = (u_long)db_get_value((db_addr_t)&tf->tf_out[7], sizeof(tf->tf_out[7]), FALSE); db_printf(" %%o7=%#lx --\n", o7); user = (type & T_KERNEL) == 0; if (user) { tpc = db_get_value((db_addr_t)&tf->tf_tpc, sizeof(tf->tf_tpc), FALSE); db_printf("userland() at "); db_printsym(tpc, DB_STGY_PROC); db_printf("\n"); db_utrace(td, tf); } return (user); } -/* - * User stack trace (debugging aid). - */ -static void -db_utrace(struct thread *td, struct trapframe *tf) +static int +db_backtrace(struct thread *td, struct frame *fp, int count) { - struct pcb *pcb; - db_addr_t sp, rsp, o7, pc; - int i, found; + struct trapframe *tf; + const char *name; + c_db_sym_t sym; + db_expr_t offset; + db_expr_t value; + db_addr_t npc; + db_addr_t pc; + int trap; + int user; - pcb = td->td_pcb; - sp = db_get_value((db_addr_t)&tf->tf_sp, sizeof(tf->tf_sp), FALSE); - o7 = db_get_value((db_addr_t)&tf->tf_out[7], sizeof(tf->tf_out[7]), - FALSE); - pc = db_get_value((db_addr_t)&tf->tf_tpc, sizeof(tf->tf_tpc), FALSE); - db_printf("user trace: trap %%o7=%#lx\n", o7); - while (sp != 0) { - db_printf("pc %#lx, sp %#lx\n", pc, sp); - /* First, check whether the frame is in the pcb. */ - found = 0; - for (i = 0; i < pcb->pcb_nsaved; i++) { - if (pcb->pcb_rwsp[i] == sp) { - found = 1; - sp = pcb->pcb_rw[i].rw_in[6]; - pc = pcb->pcb_rw[i].rw_in[7]; - break; - } + if (count == -1) + count = 1024; + + trap = 0; + user = 0; + npc = 0; + while (count-- && !user) { + pc = (db_addr_t)db_get_value((db_addr_t)&fp->fr_pc, + sizeof(fp->fr_pc), FALSE); + if (trap) { + pc = npc; + trap = 0; } - if (!found) { - rsp = sp + SPOFF; - sp = 0; - if (copyin((void *)(rsp + offsetof(struct frame, fr_fp)), - &sp, sizeof(sp)) != 0 || - copyin((void *)(rsp + offsetof(struct frame, fr_pc)), - &pc, sizeof(pc)) != 0) - break; + if (!INKERNEL((vm_offset_t)pc)) + break; + sym = db_search_symbol(pc, DB_STGY_ANY, &offset); + if (sym == C_DB_SYM_NULL) { + value = 0; + name = NULL; + } else + db_symbol_values(sym, &name, &value); + if (name == NULL) + name = "(null)"; + fp = (struct frame *)(db_get_value((db_addr_t)&fp->fr_fp, + sizeof(fp->fr_fp), FALSE) + SPOFF); + if (bcmp(name, "tl0_", 4) == 0 || + bcmp(name, "tl1_", 4) == 0) { + tf = (struct trapframe *)(fp + 1); + npc = db_get_value((db_addr_t)&tf->tf_tpc, + sizeof(tf->tf_tpc), FALSE); + user = db_print_trap(td, tf); + trap = 1; + } else { + db_printf("%s() at ", name); + db_printsym(pc, DB_STGY_PROC); + db_printf("\n"); } } - db_printf("done\n"); + return (0); } void -db_print_backtrace(void) +db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, + char *modif) { - u_long *sp; + struct thread *td; - sp = __builtin_frame_address(1); - db_stack_trace_cmd((db_expr_t)sp, TRUE, -1, "a"); + td = (have_addr) ? kdb_thr_lookup(addr) : kdb_thread; + if (td == NULL) { + db_printf("Thread %d not found\n", (int)addr); + return; + } + db_trace_thread(td, count); +} + +void +db_trace_self(void) +{ + db_expr_t addr; + + addr = (db_expr_t)__builtin_frame_address(1); + db_backtrace(curthread, (struct frame *)(addr + SPOFF), -1); +} + +int +db_trace_thread(struct thread *td, int count) +{ + struct pcb *ctx; + + ctx = kdb_thr_ctx(td); + return (db_backtrace(td, (struct frame*)(ctx->pcb_sp + SPOFF), count)); }