Mon Mar 29 03:09:42 2021 UTC ()
Expose kdbpeek() and kdbrpeek() for dtrace.


(simonb)
diff -r1.36 -r1.37 src/sys/arch/mips/include/db_machdep.h
diff -r1.7 -r1.8 src/sys/arch/mips/mips/mips_stacktrace.c

cvs diff -r1.36 -r1.37 src/sys/arch/mips/include/db_machdep.h (switch to unified diff)

--- src/sys/arch/mips/include/db_machdep.h 2021/03/29 03:07:33 1.36
+++ src/sys/arch/mips/include/db_machdep.h 2021/03/29 03:09:41 1.37
@@ -1,149 +1,155 @@ @@ -1,149 +1,155 @@
1/* $NetBSD: db_machdep.h,v 1.36 2021/03/29 03:07:33 simonb Exp $ */ 1/* $NetBSD: db_machdep.h,v 1.37 2021/03/29 03:09:41 simonb Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author) 4 * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author)
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 16 * must display the following acknowledgement:
17 * This product includes software developed by Jonathan Stone for 17 * This product includes software developed by Jonathan Stone for
18 * the NetBSD Project. 18 * the NetBSD Project.
19 * 4. The name of the author may not be used to endorse or promote products 19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission. 20 * derived from this software without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34#ifndef _MIPS_DB_MACHDEP_H_ 34#ifndef _MIPS_DB_MACHDEP_H_
35#define _MIPS_DB_MACHDEP_H_ 35#define _MIPS_DB_MACHDEP_H_
36 36
37#include <sys/types.h> 37#include <sys/types.h>
38#include <sys/stdbool.h> 38#include <sys/stdbool.h>
39 39
40#include <uvm/uvm_param.h> /* XXX boolean_t */ 40#include <uvm/uvm_param.h> /* XXX boolean_t */
41 41
42#include <mips/trap.h> /* T_BREAK */ 42#include <mips/trap.h> /* T_BREAK */
43#include <mips/reg.h> /* register state */ 43#include <mips/reg.h> /* register state */
44#include <mips/regnum.h> /* symbolic register indices */ 44#include <mips/regnum.h> /* symbolic register indices */
45#include <mips/pcb.h> 45#include <mips/pcb.h>
46 46
47#define DB_ELF_SYMBOLS 47#define DB_ELF_SYMBOLS
48 48
49typedef vaddr_t db_addr_t; /* address - unsigned */ 49typedef vaddr_t db_addr_t; /* address - unsigned */
50#ifdef __mips_n32 50#ifdef __mips_n32
51#define DDB_EXPR_FMT "ll" /* expression is long long */ 51#define DDB_EXPR_FMT "ll" /* expression is long long */
52typedef int64_t db_expr_t; /* expression - signed */ 52typedef int64_t db_expr_t; /* expression - signed */
53#else 53#else
54#define DDB_EXPR_FMT "l" /* expression is long */ 54#define DDB_EXPR_FMT "l" /* expression is long */
55typedef long db_expr_t; /* expression - signed */ 55typedef long db_expr_t; /* expression - signed */
56#endif 56#endif
57 57
58typedef struct reg db_regs_t; 58typedef struct reg db_regs_t;
59 59
60extern db_regs_t ddb_regs; /* register state */ 60extern db_regs_t ddb_regs; /* register state */
61#define DDB_REGS (&ddb_regs) 61#define DDB_REGS (&ddb_regs)
62 62
63#define PC_REGS(regs) ((regs)->r_regs[_R_PC]) 63#define PC_REGS(regs) ((regs)->r_regs[_R_PC])
64 64
65#define PC_ADVANCE(regs) do { \ 65#define PC_ADVANCE(regs) do { \
66 if ((db_get_value((regs)->r_regs[_R_PC], sizeof(int), false) &\ 66 if ((db_get_value((regs)->r_regs[_R_PC], sizeof(int), false) &\
67 0xfc00003f) == 0xd) \ 67 0xfc00003f) == 0xd) \
68 (regs)->r_regs[_R_PC] += BKPT_SIZE; \ 68 (regs)->r_regs[_R_PC] += BKPT_SIZE; \
69} while(0) 69} while(0)
70 70
71/* Similar to PC_ADVANCE(), except only advance on cpu_Debugger()'s bpt */ 71/* Similar to PC_ADVANCE(), except only advance on cpu_Debugger()'s bpt */
72#define PC_BREAK_ADVANCE(regs) do { \ 72#define PC_BREAK_ADVANCE(regs) do { \
73 if (db_get_value((regs)->r_regs[_R_PC], sizeof(int), false) == 0xd) \ 73 if (db_get_value((regs)->r_regs[_R_PC], sizeof(int), false) == 0xd) \
74 (regs)->r_regs[_R_PC] += BKPT_SIZE; \ 74 (regs)->r_regs[_R_PC] += BKPT_SIZE; \
75} while(0) 75} while(0)
76 76
77#define BKPT_ADDR(addr) (addr) /* breakpoint address */ 77#define BKPT_ADDR(addr) (addr) /* breakpoint address */
78#define BKPT_INST 0x0001000D 78#define BKPT_INST 0x0001000D
79#define BKPT_SIZE (4) /* size of breakpoint inst */ 79#define BKPT_SIZE (4) /* size of breakpoint inst */
80#define BKPT_SET(inst, addr) (BKPT_INST) 80#define BKPT_SET(inst, addr) (BKPT_INST)
81 81
82#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAK) 82#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAK)
83#define IS_WATCHPOINT_TRAP(type, code) (0) /* XXX mips3 watchpoint */ 83#define IS_WATCHPOINT_TRAP(type, code) (0) /* XXX mips3 watchpoint */
84 84
85/* 85/*
86 * Interface to disassembly (shared with mdb) 86 * Interface to disassembly (shared with mdb)
87 */ 87 */
88db_addr_t db_disasm_insn(int insn, db_addr_t loc, bool altfmt); 88db_addr_t db_disasm_insn(int insn, db_addr_t loc, bool altfmt);
89 89
90/* 90/*
91 * Entrypoints to DDB for kernel, keyboard drivers, init hook 91 * Entrypoints to DDB for kernel, keyboard drivers, init hook
92 */ 92 */
93void kdb_kbd_trap(db_regs_t *); 93void kdb_kbd_trap(db_regs_t *);
94int kdb_trap(int type, struct reg *); 94int kdb_trap(int type, struct reg *);
95 95
96static inline void 96static inline void
97db_set_ddb_regs(int type, struct reg *regs) 97db_set_ddb_regs(int type, struct reg *regs)
98{ 98{
99 ddb_regs = *regs; 99 ddb_regs = *regs;
100} 100}
101 101
 102/*
 103 * Helper functions for fetching 32-bit and 64-bit kernel memory.
 104 */
 105bool kdbpeek(vaddr_t, unsigned *);
 106mips_reg_t kdbrpeek(vaddr_t addr, size_t n);
 107
102 108
103/* 109/*
104 * Constants for KGDB. 110 * Constants for KGDB.
105 */ 111 */
106typedef mips_reg_t kgdb_reg_t; 112typedef mips_reg_t kgdb_reg_t;
107#define KGDB_NUMREGS 90 113#define KGDB_NUMREGS 90
108#define KGDB_BUFLEN 1024 114#define KGDB_BUFLEN 1024
109 115
110/* 116/*
111 * MIPS cpus have no hardware single-step. 117 * MIPS cpus have no hardware single-step.
112 */ 118 */
113#define SOFTWARE_SSTEP 119#define SOFTWARE_SSTEP
114 120
115#define inst_trap_return(ins) ((ins)&0) 121#define inst_trap_return(ins) ((ins)&0)
116 122
117bool inst_branch(int inst); 123bool inst_branch(int inst);
118bool inst_call(int inst); 124bool inst_call(int inst);
119bool inst_return(int inst); 125bool inst_return(int inst);
120bool inst_load(int inst); 126bool inst_load(int inst);
121bool inst_store(int inst); 127bool inst_store(int inst);
122bool inst_unconditional_flow_transfer(int inst); 128bool inst_unconditional_flow_transfer(int inst);
123db_addr_t branch_taken(int inst, db_addr_t pc, db_regs_t *regs); 129db_addr_t branch_taken(int inst, db_addr_t pc, db_regs_t *regs);
124db_addr_t next_instr_address(db_addr_t pc, bool bd); 130db_addr_t next_instr_address(db_addr_t pc, bool bd);
125 131
126bool ddb_running_on_this_cpu_p(void); 132bool ddb_running_on_this_cpu_p(void);
127bool ddb_running_on_any_cpu_p(void); 133bool ddb_running_on_any_cpu_p(void);
128void db_resume_others(void); 134void db_resume_others(void);
129void db_mips_stack_trace(void *, void *, void (*pr)(const char *, ...)); 135void db_mips_stack_trace(void *, void *, void (*pr)(const char *, ...));
130 136
131 137
132#ifdef _KERNEL 138#ifdef _KERNEL
133/* 139/*
134 * Optional function to perform machine- or cpu-specific reset. 140 * Optional function to perform machine- or cpu-specific reset.
135 * Called from ddb "machine reset". 141 * Called from ddb "machine reset".
136 */ 142 */
137extern void (*cpu_reset_address)(void); 143extern void (*cpu_reset_address)(void);
138 144
139/* 145/*
140 * We have machine-dependent commands. 146 * We have machine-dependent commands.
141 */ 147 */
142#define DB_MACHINE_COMMANDS 148#define DB_MACHINE_COMMANDS
143#endif 149#endif
144 150
145#define db_stacktrace_print(prfunc) \ 151#define db_stacktrace_print(prfunc) \
146 db_mips_stack_trace(__builtin_return_address(0), \ 152 db_mips_stack_trace(__builtin_return_address(0), \
147 __builtin_frame_address(0), prfunc) 153 __builtin_frame_address(0), prfunc)
148 154
149#endif /* _MIPS_DB_MACHDEP_H_ */ 155#endif /* _MIPS_DB_MACHDEP_H_ */

cvs diff -r1.7 -r1.8 src/sys/arch/mips/mips/mips_stacktrace.c (switch to unified diff)

--- src/sys/arch/mips/mips/mips_stacktrace.c 2020/09/24 03:17:18 1.7
+++ src/sys/arch/mips/mips/mips_stacktrace.c 2021/03/29 03:09:42 1.8
@@ -1,533 +1,533 @@ @@ -1,533 +1,533 @@
1/* $NetBSD: mips_stacktrace.c,v 1.7 2020/09/24 03:17:18 mrg Exp $ */ 1/* $NetBSD: mips_stacktrace.c,v 1.8 2021/03/29 03:09:42 simonb Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988 University of Utah. 4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1992, 1993 5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved. 6 * The Regents of the University of California. All rights reserved.
7 * 7 *
8 * This code is derived from software contributed to Berkeley by 8 * This code is derived from software contributed to Berkeley by
9 * the Systems Programming Group of the University of Utah Computer 9 * the Systems Programming Group of the University of Utah Computer
10 * Science Department and Ralph Campbell. 10 * Science Department and Ralph Campbell.
11 * 11 *
12 * Redistribution and use in source and binary forms, with or without 12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions 13 * modification, are permitted provided that the following conditions
14 * are met: 14 * are met:
15 * 1. Redistributions of source code must retain the above copyright 15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer. 16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright 17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the 18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution. 19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors 20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software 21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission. 22 * without specific prior written permission.
23 * 23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE. 34 * SUCH DAMAGE.
35 * 35 *
36 * from: NetBSD: trap.c,v 1.255 2020/07/13 09:00:40 simonb Exp 36 * from: NetBSD: trap.c,v 1.255 2020/07/13 09:00:40 simonb Exp
37 * from: Utah Hdr: trap.c 1.32 91/04/06 37 * from: Utah Hdr: trap.c 1.32 91/04/06
38 * 38 *
39 * @(#)trap.c 8.5 (Berkeley) 1/11/94 39 * @(#)trap.c 8.5 (Berkeley) 1/11/94
40 */ 40 */
41 41
42#include <sys/cdefs.h> 42#include <sys/cdefs.h>
43__KERNEL_RCSID(0, "$NetBSD: mips_stacktrace.c,v 1.7 2020/09/24 03:17:18 mrg Exp $"); 43__KERNEL_RCSID(0, "$NetBSD: mips_stacktrace.c,v 1.8 2021/03/29 03:09:42 simonb Exp $");
44 44
45#ifdef _KERNEL_OPT 45#ifdef _KERNEL_OPT
46#include "opt_ddb.h" 46#include "opt_ddb.h"
47#include "opt_kgdb.h" 47#include "opt_kgdb.h"
48#endif 48#endif
49 49
50#include <sys/param.h> 50#include <sys/param.h>
51#include <sys/systm.h> 51#include <sys/systm.h>
52#include <sys/proc.h> 52#include <sys/proc.h>
53 53
54#include <mips/locore.h> 54#include <mips/locore.h>
55#include <mips/mips_opcode.h> 55#include <mips/mips_opcode.h>
56#include <mips/regnum.h> 56#include <mips/regnum.h>
57#include <mips/stacktrace.h> 57#include <mips/stacktrace.h>
58 58
59#if defined(_KMEMUSER) && !defined(DDB) 59#if defined(_KMEMUSER) && !defined(DDB)
60#define DDB 1 60#define DDB 1
61#endif 61#endif
62 62
63#ifdef DDB 63#ifdef DDB
64#include <machine/db_machdep.h> 64#include <machine/db_machdep.h>
65#include <ddb/db_sym.h> 65#include <ddb/db_sym.h>
66#include <ddb/db_user.h> 66#include <ddb/db_user.h>
67#include <ddb/db_access.h> 67#include <ddb/db_access.h>
68#endif 68#endif
69 69
70#ifdef KGDB 70#ifdef KGDB
71#include <sys/kgdb.h> 71#include <sys/kgdb.h>
72#endif 72#endif
73 73
74#ifndef DDB_TRACE 74#ifndef DDB_TRACE
75 75
76#if defined(DEBUG) || defined(DDB) || defined(KGDB) || defined(geo) 76#if defined(DEBUG) || defined(DDB) || defined(KGDB) || defined(geo)
77 77
78extern char start[], edata[], verylocore[]; 78extern char start[], edata[], verylocore[];
79#ifdef MIPS1 79#ifdef MIPS1
80extern char mips1_kern_gen_exception[]; 80extern char mips1_kern_gen_exception[];
81extern char mips1_user_gen_exception[]; 81extern char mips1_user_gen_exception[];
82extern char mips1_kern_intr[]; 82extern char mips1_kern_intr[];
83extern char mips1_user_intr[]; 83extern char mips1_user_intr[];
84extern char mips1_systemcall[]; 84extern char mips1_systemcall[];
85#endif 85#endif
86#ifdef MIPS3 86#ifdef MIPS3
87extern char mips3_kern_gen_exception[]; 87extern char mips3_kern_gen_exception[];
88extern char mips3_user_gen_exception[]; 88extern char mips3_user_gen_exception[];
89extern char mips3_kern_intr[]; 89extern char mips3_kern_intr[];
90extern char mips3_user_intr[]; 90extern char mips3_user_intr[];
91extern char mips3_systemcall[]; 91extern char mips3_systemcall[];
92#endif 92#endif
93#ifdef MIPS32 93#ifdef MIPS32
94extern char mips32_kern_gen_exception[]; 94extern char mips32_kern_gen_exception[];
95extern char mips32_user_gen_exception[]; 95extern char mips32_user_gen_exception[];
96extern char mips32_kern_intr[]; 96extern char mips32_kern_intr[];
97extern char mips32_user_intr[]; 97extern char mips32_user_intr[];
98extern char mips32_systemcall[]; 98extern char mips32_systemcall[];
99#endif 99#endif
100#ifdef MIPS32R2 100#ifdef MIPS32R2
101extern char mips32r2_kern_gen_exception[]; 101extern char mips32r2_kern_gen_exception[];
102extern char mips32r2_user_gen_exception[]; 102extern char mips32r2_user_gen_exception[];
103extern char mips32r2_kern_intr[]; 103extern char mips32r2_kern_intr[];
104extern char mips32r2_user_intr[]; 104extern char mips32r2_user_intr[];
105extern char mips32r2_systemcall[]; 105extern char mips32r2_systemcall[];
106#endif 106#endif
107#ifdef MIPS64 107#ifdef MIPS64
108extern char mips64_kern_gen_exception[]; 108extern char mips64_kern_gen_exception[];
109extern char mips64_user_gen_exception[]; 109extern char mips64_user_gen_exception[];
110extern char mips64_kern_intr[]; 110extern char mips64_kern_intr[];
111extern char mips64_user_intr[]; 111extern char mips64_user_intr[];
112extern char mips64_systemcall[]; 112extern char mips64_systemcall[];
113#endif 113#endif
114#ifdef MIPS64R2 114#ifdef MIPS64R2
115extern char mips64r2_kern_gen_exception[]; 115extern char mips64r2_kern_gen_exception[];
116extern char mips64r2_user_gen_exception[]; 116extern char mips64r2_user_gen_exception[];
117extern char mips64r2_kern_intr[]; 117extern char mips64r2_kern_intr[];
118extern char mips64r2_user_intr[]; 118extern char mips64r2_user_intr[];
119extern char mips64r2_systemcall[]; 119extern char mips64r2_systemcall[];
120#endif 120#endif
121 121
122#define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */ 122#define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */
123#define MIPS_JR_K0 0x03400008 /* instruction code for jr k0 */ 123#define MIPS_JR_K0 0x03400008 /* instruction code for jr k0 */
124#define MIPS_ERET 0x42000018 /* instruction code for eret */ 124#define MIPS_ERET 0x42000018 /* instruction code for eret */
125 125
126int main(void *); /* XXX */ 126int main(void *); /* XXX */
127 127
128/* 128/*
129 * Functions ``special'' enough to print by name 129 * Functions ``special'' enough to print by name
130 */ 130 */
131#define Name(_fn) { (void*)_fn, # _fn } 131#define Name(_fn) { (void*)_fn, # _fn }
132static const struct { void *addr; const char *name;} names[] = { 132static const struct { void *addr; const char *name;} names[] = {
133#ifdef _KERNEL 133#ifdef _KERNEL
134 Name(stacktrace), 134 Name(stacktrace),
135 Name(stacktrace_subr), 135 Name(stacktrace_subr),
136 Name(main), 136 Name(main),
137 Name(trap), 137 Name(trap),
138 138
139#ifdef MIPS1 /* r2000 family (mips-I CPU) */ 139#ifdef MIPS1 /* r2000 family (mips-I CPU) */
140 Name(mips1_kern_gen_exception), 140 Name(mips1_kern_gen_exception),
141 Name(mips1_user_gen_exception), 141 Name(mips1_user_gen_exception),
142 Name(mips1_systemcall), 142 Name(mips1_systemcall),
143 Name(mips1_kern_intr), 143 Name(mips1_kern_intr),
144 Name(mips1_user_intr), 144 Name(mips1_user_intr),
145#endif /* MIPS1 */ 145#endif /* MIPS1 */
146 146
147#if defined(MIPS3) /* r4000 family (mips-III CPU) */ 147#if defined(MIPS3) /* r4000 family (mips-III CPU) */
148 Name(mips3_kern_gen_exception), 148 Name(mips3_kern_gen_exception),
149 Name(mips3_user_gen_exception), 149 Name(mips3_user_gen_exception),
150 Name(mips3_systemcall), 150 Name(mips3_systemcall),
151 Name(mips3_kern_intr), 151 Name(mips3_kern_intr),
152 Name(mips3_user_intr), 152 Name(mips3_user_intr),
153#endif /* MIPS3 */ 153#endif /* MIPS3 */
154 154
155#if defined(MIPS32) /* MIPS32 family (mips-III CPU) */ 155#if defined(MIPS32) /* MIPS32 family (mips-III CPU) */
156 Name(mips32_kern_gen_exception), 156 Name(mips32_kern_gen_exception),
157 Name(mips32_user_gen_exception), 157 Name(mips32_user_gen_exception),
158 Name(mips32_systemcall), 158 Name(mips32_systemcall),
159 Name(mips32_kern_intr), 159 Name(mips32_kern_intr),
160 Name(mips32_user_intr), 160 Name(mips32_user_intr),
161#endif /* MIPS32 */ 161#endif /* MIPS32 */
162 162
163#if defined(MIPS32R2) /* MIPS32R2 family (mips-III CPU) */ 163#if defined(MIPS32R2) /* MIPS32R2 family (mips-III CPU) */
164 Name(mips32r2_kern_gen_exception), 164 Name(mips32r2_kern_gen_exception),
165 Name(mips32r2_user_gen_exception), 165 Name(mips32r2_user_gen_exception),
166 Name(mips32r2_systemcall), 166 Name(mips32r2_systemcall),
167 Name(mips32r2_kern_intr), 167 Name(mips32r2_kern_intr),
168 Name(mips32r2_user_intr), 168 Name(mips32r2_user_intr),
169#endif /* MIPS32R2 */ 169#endif /* MIPS32R2 */
170 170
171#if defined(MIPS64) /* MIPS64 family (mips-III CPU) */ 171#if defined(MIPS64) /* MIPS64 family (mips-III CPU) */
172 Name(mips64_kern_gen_exception), 172 Name(mips64_kern_gen_exception),
173 Name(mips64_user_gen_exception), 173 Name(mips64_user_gen_exception),
174 Name(mips64_systemcall), 174 Name(mips64_systemcall),
175 Name(mips64_kern_intr), 175 Name(mips64_kern_intr),
176 Name(mips64_user_intr), 176 Name(mips64_user_intr),
177#endif /* MIPS64 */ 177#endif /* MIPS64 */
178 178
179#if defined(MIPS64R2) /* MIPS64R2 family (mips-III CPU) */ 179#if defined(MIPS64R2) /* MIPS64R2 family (mips-III CPU) */
180 Name(mips64r2_kern_gen_exception), 180 Name(mips64r2_kern_gen_exception),
181 Name(mips64r2_user_gen_exception), 181 Name(mips64r2_user_gen_exception),
182 Name(mips64r2_systemcall), 182 Name(mips64r2_systemcall),
183 Name(mips64r2_kern_intr), 183 Name(mips64r2_kern_intr),
184 Name(mips64r2_user_intr), 184 Name(mips64r2_user_intr),
185#endif /* MIPS64R2 */ 185#endif /* MIPS64R2 */
186 186
187 Name(cpu_idle), 187 Name(cpu_idle),
188 Name(cpu_switchto), 188 Name(cpu_switchto),
189#endif /* _KERNEL */ 189#endif /* _KERNEL */
190 {0, 0} 190 {0, 0}
191}; 191};
192 192
193 193
194static bool 194bool
195kdbpeek(vaddr_t addr, unsigned *valp) 195kdbpeek(vaddr_t addr, unsigned *valp)
196{ 196{
197 if (addr & 3) { 197 if (addr & 3) {
198 printf("kdbpeek: unaligned address %#"PRIxVADDR"\n", addr); 198 printf("kdbpeek: unaligned address %#"PRIxVADDR"\n", addr);
199 /* We might have been called from DDB, so do not go there. */ 199 /* We might have been called from DDB, so do not go there. */
200 return false; 200 return false;
201 } else if (addr == 0) { 201 } else if (addr == 0) {
202 printf("kdbpeek: NULL\n"); 202 printf("kdbpeek: NULL\n");
203 return false; 203 return false;
204 } else { 204 } else {
205#if _KERNEL 205#if _KERNEL
206 *valp = *(unsigned *)addr; 206 *valp = *(unsigned *)addr;
207#else 207#else
208 db_read_bytes((db_addr_t)addr, sizeof(unsigned), (char *)valp); 208 db_read_bytes((db_addr_t)addr, sizeof(unsigned), (char *)valp);
209#endif 209#endif
210 return true; 210 return true;
211 } 211 }
212} 212}
213 213
214static mips_reg_t 214mips_reg_t
215kdbrpeek(vaddr_t addr, size_t n) 215kdbrpeek(vaddr_t addr, size_t n)
216{ 216{
217 mips_reg_t rc = 0; 217 mips_reg_t rc = 0;
218 218
219 if (addr & (n - 1)) { 219 if (addr & (n - 1)) {
220 printf("kdbrpeek: unaligned address %#"PRIxVADDR"\n", addr); 220 printf("kdbrpeek: unaligned address %#"PRIxVADDR"\n", addr);
221#if _KERNEL 221#if _KERNEL
222 /* We might have been called from DDB, so do not go there. */ 222 /* We might have been called from DDB, so do not go there. */
223 stacktrace(); 223 stacktrace();
224#endif 224#endif
225 rc = -1; 225 rc = -1;
226 } else if (addr == 0) { 226 } else if (addr == 0) {
227 printf("kdbrpeek: NULL\n"); 227 printf("kdbrpeek: NULL\n");
228 rc = 0xdeadfeed; 228 rc = 0xdeadfeed;
229 } else { 229 } else {
230 if (sizeof(mips_reg_t) == 8 && n == 8) 230 if (sizeof(mips_reg_t) == 8 && n == 8)
231#if _KERNEL 231#if _KERNEL
232 rc = *(int64_t *)addr; 232 rc = *(int64_t *)addr;
233 else 233 else
234 rc = *(int32_t *)addr; 234 rc = *(int32_t *)addr;
235#else 235#else
236 db_read_bytes((db_addr_t)addr, sizeof(int64_t), (char *)&rc); 236 db_read_bytes((db_addr_t)addr, sizeof(int64_t), (char *)&rc);
237 else 237 else
238 db_read_bytes((db_addr_t)addr, sizeof(int32_t), (char *)&rc); 238 db_read_bytes((db_addr_t)addr, sizeof(int32_t), (char *)&rc);
239#endif 239#endif
240 } 240 }
241 return rc; 241 return rc;
242} 242}
243 243
244/* 244/*
245 * Map a function address to a string name, if known; or a hex string. 245 * Map a function address to a string name, if known; or a hex string.
246 */ 246 */
247static const char * 247static const char *
248fn_name(vaddr_t addr) 248fn_name(vaddr_t addr)
249{ 249{
250 static char buf[17]; 250 static char buf[17];
251 int i = 0; 251 int i = 0;
252#ifdef DDB 252#ifdef DDB
253 db_expr_t diff; 253 db_expr_t diff;
254 db_sym_t sym; 254 db_sym_t sym;
255 const char *symname; 255 const char *symname;
256#endif 256#endif
257 257
258#ifdef DDB 258#ifdef DDB
259 diff = 0; 259 diff = 0;
260 symname = NULL; 260 symname = NULL;
261 sym = db_search_symbol(addr, DB_STGY_ANY, &diff); 261 sym = db_search_symbol(addr, DB_STGY_ANY, &diff);
262 db_symbol_values(sym, &symname, 0); 262 db_symbol_values(sym, &symname, 0);
263 if (symname && diff == 0) 263 if (symname && diff == 0)
264 return (symname); 264 return (symname);
265#endif 265#endif
266 for (i = 0; names[i].name; i++) 266 for (i = 0; names[i].name; i++)
267 if (names[i].addr == (void*)addr) 267 if (names[i].addr == (void*)addr)
268 return (names[i].name); 268 return (names[i].name);
269 snprintf(buf, sizeof(buf), "%#"PRIxVADDR, addr); 269 snprintf(buf, sizeof(buf), "%#"PRIxVADDR, addr);
270 return (buf); 270 return (buf);
271} 271}
272 272
273/* 273/*
274 * Do a stack backtrace. 274 * Do a stack backtrace.
275 * (*printfn)() prints the output to either the system log, 275 * (*printfn)() prints the output to either the system log,
276 * the console, or both. 276 * the console, or both.
277 */ 277 */
278void 278void
279stacktrace_subr(mips_reg_t a0, mips_reg_t a1, mips_reg_t a2, mips_reg_t a3, 279stacktrace_subr(mips_reg_t a0, mips_reg_t a1, mips_reg_t a2, mips_reg_t a3,
280 vaddr_t pc, vaddr_t sp, vaddr_t fp, vaddr_t ra, 280 vaddr_t pc, vaddr_t sp, vaddr_t fp, vaddr_t ra,
281 void (*printfn)(const char*, ...)) 281 void (*printfn)(const char*, ...))
282{ 282{
283 vaddr_t va, subr; 283 vaddr_t va, subr;
284 unsigned instr, mask; 284 unsigned instr, mask;
285 InstFmt i; 285 InstFmt i;
286 int more, stksize; 286 int more, stksize;
287 unsigned int frames = 0; 287 unsigned int frames = 0;
288 int foundframesize = 0; 288 int foundframesize = 0;
289 mips_reg_t regs[32] = { 289 mips_reg_t regs[32] = {
290 [_R_ZERO] = 0, 290 [_R_ZERO] = 0,
291 [_R_A0] = a0, [_R_A1] = a1, [_R_A2] = a2, [_R_A3] = a3, 291 [_R_A0] = a0, [_R_A1] = a1, [_R_A2] = a2, [_R_A3] = a3,
292 [_R_RA] = ra, 292 [_R_RA] = ra,
293 }; 293 };
294 294
295/* Jump here when done with a frame, to start a new one */ 295/* Jump here when done with a frame, to start a new one */
296loop: 296loop:
297 stksize = 0; 297 stksize = 0;
298 subr = 0; 298 subr = 0;
299 mask = 1; 299 mask = 1;
300 if (frames++ > 100) { 300 if (frames++ > 100) {
301 (*printfn)("\nstackframe count exceeded\n"); 301 (*printfn)("\nstackframe count exceeded\n");
302 /* return breaks stackframe-size heuristics with gcc -O2 */ 302 /* return breaks stackframe-size heuristics with gcc -O2 */
303 goto finish; /*XXX*/ 303 goto finish; /*XXX*/
304 } 304 }
305 305
306 /* check for bad SP: could foul up next frame */ 306 /* check for bad SP: could foul up next frame */
307 if ((sp & (sizeof(sp)-1)) || (intptr_t)sp >= 0) { 307 if ((sp & (sizeof(sp)-1)) || (intptr_t)sp >= 0) {
308 (*printfn)("SP 0x%x: not in kernel\n", sp); 308 (*printfn)("SP 0x%x: not in kernel\n", sp);
309 ra = 0; 309 ra = 0;
310 subr = 0; 310 subr = 0;
311 goto done; 311 goto done;
312 } 312 }
313 313
314 /* Check for bad PC */ 314 /* Check for bad PC */
315 if (pc & 3 || (intptr_t)pc >= 0 || (intptr_t)pc >= (intptr_t)edata) { 315 if (pc & 3 || (intptr_t)pc >= 0 || (intptr_t)pc >= (intptr_t)edata) {
316 (*printfn)("PC 0x%x: not in kernel space\n", pc); 316 (*printfn)("PC 0x%x: not in kernel space\n", pc);
317 ra = 0; 317 ra = 0;
318 goto done; 318 goto done;
319 } 319 }
320 320
321#if defined(DDB) && defined(_KERNEL) 321#if defined(DDB) && defined(_KERNEL)
322 if (ksyms_available()) { 322 if (ksyms_available()) {
323 db_expr_t diff; 323 db_expr_t diff;
324 db_sym_t sym; 324 db_sym_t sym;
325 325
326 /* 326 /*
327 * Check the kernel symbol table to see the beginning of 327 * Check the kernel symbol table to see the beginning of
328 * the current subroutine. 328 * the current subroutine.
329 */ 329 */
330 diff = 0; 330 diff = 0;
331 sym = db_search_symbol(pc, DB_STGY_ANY, &diff); 331 sym = db_search_symbol(pc, DB_STGY_ANY, &diff);
332 if (sym != DB_SYM_NULL && diff == 0) { 332 if (sym != DB_SYM_NULL && diff == 0) {
333 /* check func(foo) __attribute__((__noreturn__)) case */ 333 /* check func(foo) __attribute__((__noreturn__)) case */
334 if (!kdbpeek(pc - 2 * sizeof(unsigned), &instr)) 334 if (!kdbpeek(pc - 2 * sizeof(unsigned), &instr))
335 return; 335 return;
336 i.word = instr; 336 i.word = instr;
337 if (i.JType.op == OP_JAL) { 337 if (i.JType.op == OP_JAL) {
338 sym = db_search_symbol(pc - sizeof(int), 338 sym = db_search_symbol(pc - sizeof(int),
339 DB_STGY_ANY, &diff); 339 DB_STGY_ANY, &diff);
340 if (sym != DB_SYM_NULL && diff != 0) 340 if (sym != DB_SYM_NULL && diff != 0)
341 diff += sizeof(int); 341 diff += sizeof(int);
342 } 342 }
343 } 343 }
344 if (sym == DB_SYM_NULL) { 344 if (sym == DB_SYM_NULL) {
345 ra = 0; 345 ra = 0;
346 goto done; 346 goto done;
347 } 347 }
348 va = pc - diff; 348 va = pc - diff;
349 } else { 349 } else {
350#endif /* DDB && _KERNEL */ 350#endif /* DDB && _KERNEL */
351 /* 351 /*
352 * Find the beginning of the current subroutine by 352 * Find the beginning of the current subroutine by
353 * scanning backwards from the current PC for the end 353 * scanning backwards from the current PC for the end
354 * of the previous subroutine. 354 * of the previous subroutine.
355 * 355 *
356 * XXX This won't work well because nowadays gcc is so 356 * XXX This won't work well because nowadays gcc is so
357 * aggressive as to reorder instruction blocks for 357 * aggressive as to reorder instruction blocks for
358 * branch-predict. (i.e. 'jr ra' wouldn't indicate 358 * branch-predict. (i.e. 'jr ra' wouldn't indicate
359 * the end of subroutine) 359 * the end of subroutine)
360 */ 360 */
361 va = pc; 361 va = pc;
362 do { 362 do {
363 va -= sizeof(int); 363 va -= sizeof(int);
364#ifdef _KERNEL /* XXX crash */ 364#ifdef _KERNEL /* XXX crash */
365 if (va <= (vaddr_t)verylocore) 365 if (va <= (vaddr_t)verylocore)
366 goto finish; 366 goto finish;
367#endif 367#endif
368 if (!kdbpeek(va, &instr)) 368 if (!kdbpeek(va, &instr))
369 return; 369 return;
370 if (instr == MIPS_ERET) 370 if (instr == MIPS_ERET)
371 goto mips3_eret; 371 goto mips3_eret;
372 } while (instr != MIPS_JR_RA && instr != MIPS_JR_K0); 372 } while (instr != MIPS_JR_RA && instr != MIPS_JR_K0);
373 /* skip back over branch & delay slot */ 373 /* skip back over branch & delay slot */
374 va += sizeof(int); 374 va += sizeof(int);
375mips3_eret: 375mips3_eret:
376 va += sizeof(int); 376 va += sizeof(int);
377 /* skip over nulls which might separate .o files */ 377 /* skip over nulls which might separate .o files */
378 instr = 0; 378 instr = 0;
379 while (instr == 0) { 379 while (instr == 0) {
380 if (!kdbpeek(va, &instr)) 380 if (!kdbpeek(va, &instr))
381 return; 381 return;
382 va += sizeof(int); 382 va += sizeof(int);
383 } 383 }
384#if defined(DDB) && defined(_KERNEL) 384#if defined(DDB) && defined(_KERNEL)
385 } 385 }
386#endif /* DDB && _KERNEL */ 386#endif /* DDB && _KERNEL */
387 subr = va; 387 subr = va;
388 388
389 /* scan forwards to find stack size and any saved registers */ 389 /* scan forwards to find stack size and any saved registers */
390 stksize = 0; 390 stksize = 0;
391 more = 3; 391 more = 3;
392 mask &= 0x40ff0001; /* if s0-s8 are valid, leave then as valid */ 392 mask &= 0x40ff0001; /* if s0-s8 are valid, leave then as valid */
393 foundframesize = 0; 393 foundframesize = 0;
394 for (va = subr; more; va += sizeof(int), 394 for (va = subr; more; va += sizeof(int),
395 more = (more == 3) ? 3 : more - 1) { 395 more = (more == 3) ? 3 : more - 1) {
396 /* stop if hit our current position */ 396 /* stop if hit our current position */
397 if (va >= pc) 397 if (va >= pc)
398 break; 398 break;
399 if (!kdbpeek(va, &instr)) 399 if (!kdbpeek(va, &instr))
400 return; 400 return;
401 i.word = instr; 401 i.word = instr;
402 switch (i.JType.op) { 402 switch (i.JType.op) {
403 case OP_SPECIAL: 403 case OP_SPECIAL:
404 switch (i.RType.func) { 404 switch (i.RType.func) {
405 case OP_JR: 405 case OP_JR:
406 case OP_JALR: 406 case OP_JALR:
407 more = 2; /* stop after next instruction */ 407 more = 2; /* stop after next instruction */
408 break; 408 break;
409 409
410 case OP_ADD: 410 case OP_ADD:
411 case OP_ADDU: 411 case OP_ADDU:
412 case OP_DADD: 412 case OP_DADD:
413 case OP_DADDU: 413 case OP_DADDU:
414 if (!(mask & (1 << i.RType.rd)) 414 if (!(mask & (1 << i.RType.rd))
415 || !(mask & (1 << i.RType.rt))) 415 || !(mask & (1 << i.RType.rt)))
416 break; 416 break;
417 if (i.RType.rd != _R_ZERO) 417 if (i.RType.rd != _R_ZERO)
418 break; 418 break;
419 mask |= (1 << i.RType.rs); 419 mask |= (1 << i.RType.rs);
420 regs[i.RType.rs] = regs[i.RType.rt]; 420 regs[i.RType.rs] = regs[i.RType.rt];
421 if (i.RType.func >= OP_DADD) 421 if (i.RType.func >= OP_DADD)
422 break; 422 break;
423 regs[i.RType.rs] = (int32_t)regs[i.RType.rs]; 423 regs[i.RType.rs] = (int32_t)regs[i.RType.rs];
424 break; 424 break;
425 425
426 case OP_SYSCALL: 426 case OP_SYSCALL:
427 case OP_BREAK: 427 case OP_BREAK:
428 more = 1; /* stop now */ 428 more = 1; /* stop now */
429 break; 429 break;
430 } 430 }
431 break; 431 break;
432 432
433 case OP_REGIMM: 433 case OP_REGIMM:
434 case OP_J: 434 case OP_J:
435 case OP_JAL: 435 case OP_JAL:
436 case OP_BEQ: 436 case OP_BEQ:
437 case OP_BNE: 437 case OP_BNE:
438 case OP_BLEZ: 438 case OP_BLEZ:
439 case OP_BGTZ: 439 case OP_BGTZ:
440 more = 2; /* stop after next instruction */ 440 more = 2; /* stop after next instruction */
441 break; 441 break;
442 442
443 case OP_COP0: 443 case OP_COP0:
444 case OP_COP1: 444 case OP_COP1:
445 case OP_COP2: 445 case OP_COP2:
446 case OP_COP3: 446 case OP_COP3:
447 switch (i.RType.rs) { 447 switch (i.RType.rs) {
448 case OP_BCx: 448 case OP_BCx:
449 case OP_BCy: 449 case OP_BCy:
450 more = 2; /* stop after next instruction */ 450 more = 2; /* stop after next instruction */
451 }; 451 };
452 break; 452 break;
453 453
454 case OP_SW: 454 case OP_SW:
455#if !defined(__mips_o32) 455#if !defined(__mips_o32)
456 case OP_SD: 456 case OP_SD:
457#endif 457#endif
458 { 458 {
459 size_t size = (i.JType.op == OP_SW) ? 4 : 8; 459 size_t size = (i.JType.op == OP_SW) ? 4 : 8;
460 460
461 /* look for saved registers on the stack */ 461 /* look for saved registers on the stack */
462 if (i.IType.rs != _R_SP) 462 if (i.IType.rs != _R_SP)
463 break; 463 break;
464 switch (i.IType.rt) { 464 switch (i.IType.rt) {
465 case _R_A0: /* a0 */ 465 case _R_A0: /* a0 */
466 case _R_A1: /* a1 */ 466 case _R_A1: /* a1 */
467 case _R_A2: /* a2 */ 467 case _R_A2: /* a2 */
468 case _R_A3: /* a3 */ 468 case _R_A3: /* a3 */
469 case _R_S0: /* s0 */ 469 case _R_S0: /* s0 */
470 case _R_S1: /* s1 */ 470 case _R_S1: /* s1 */
471 case _R_S2: /* s2 */ 471 case _R_S2: /* s2 */
472 case _R_S3: /* s3 */ 472 case _R_S3: /* s3 */
473 case _R_S4: /* s4 */ 473 case _R_S4: /* s4 */
474 case _R_S5: /* s5 */ 474 case _R_S5: /* s5 */
475 case _R_S6: /* s6 */ 475 case _R_S6: /* s6 */
476 case _R_S7: /* s7 */ 476 case _R_S7: /* s7 */
477 case _R_S8: /* s8 */ 477 case _R_S8: /* s8 */
478 case _R_RA: /* ra */ 478 case _R_RA: /* ra */
479 regs[i.IType.rt] = 479 regs[i.IType.rt] =
480 kdbrpeek(sp + (int16_t)i.IType.imm, size); 480 kdbrpeek(sp + (int16_t)i.IType.imm, size);
481 mask |= (1 << i.IType.rt); 481 mask |= (1 << i.IType.rt);
482 break; 482 break;
483 } 483 }
484 break; 484 break;
485 } 485 }
486 486
487 case OP_ADDI: 487 case OP_ADDI:
488 case OP_ADDIU: 488 case OP_ADDIU:
489#if !defined(__mips_o32) 489#if !defined(__mips_o32)
490 case OP_DADDI: 490 case OP_DADDI:
491 case OP_DADDIU: 491 case OP_DADDIU:
492#endif 492#endif
493 /* look for stack pointer adjustment */ 493 /* look for stack pointer adjustment */
494 if (i.IType.rs != _R_SP || i.IType.rt != _R_SP) 494 if (i.IType.rs != _R_SP || i.IType.rt != _R_SP)
495 break; 495 break;
496 /* don't count pops for mcount */ 496 /* don't count pops for mcount */
497 if (!foundframesize) { 497 if (!foundframesize) {
498 stksize = - ((short)i.IType.imm); 498 stksize = - ((short)i.IType.imm);
499 foundframesize = 1; 499 foundframesize = 1;
500 } 500 }
501 break; 501 break;
502 } 502 }
503 } 503 }
504done: 504done:
505 if (mask & (1 << _R_RA)) 505 if (mask & (1 << _R_RA))
506 ra = regs[_R_RA]; 506 ra = regs[_R_RA];
507 (*printfn)("%#"PRIxVADDR": %s+%"PRIxVADDR" (%"PRIxREGISTER",%"PRIxREGISTER",%"PRIxREGISTER",%"PRIxREGISTER") ra %"PRIxVADDR" sz %d\n", 507 (*printfn)("%#"PRIxVADDR": %s+%"PRIxVADDR" (%"PRIxREGISTER",%"PRIxREGISTER",%"PRIxREGISTER",%"PRIxREGISTER") ra %"PRIxVADDR" sz %d\n",
508 sp, fn_name(subr), pc - subr, 508 sp, fn_name(subr), pc - subr,
509 regs[_R_A0], regs[_R_A1], regs[_R_A2], regs[_R_A3], 509 regs[_R_A0], regs[_R_A1], regs[_R_A2], regs[_R_A3],
510 ra, stksize); 510 ra, stksize);
511 511
512 if (ra) { 512 if (ra) {
513 if (pc == ra && stksize == 0) 513 if (pc == ra && stksize == 0)
514 (*printfn)("stacktrace: loop!\n"); 514 (*printfn)("stacktrace: loop!\n");
515 else { 515 else {
516 pc = ra; 516 pc = ra;
517 sp += stksize; 517 sp += stksize;
518 ra = 0; 518 ra = 0;
519 goto loop; 519 goto loop;
520 } 520 }
521 } else { 521 } else {
522finish: 522finish:
523#ifdef _KERNEL 523#ifdef _KERNEL
524 (*printfn)("User-level: pid %d.%d\n", 524 (*printfn)("User-level: pid %d.%d\n",
525 curlwp->l_proc->p_pid, curlwp->l_lid); 525 curlwp->l_proc->p_pid, curlwp->l_lid);
526#else 526#else
527 (*printfn)("User-level: FIXME\n"); 527 (*printfn)("User-level: FIXME\n");
528#endif 528#endif
529 } 529 }
530} 530}
531 531
532#endif /* DEBUG || DDB || KGDB || geo */ 532#endif /* DEBUG || DDB || KGDB || geo */
533#endif /* DDB_TRACE */ 533#endif /* DDB_TRACE */