Improve ddb disassembly for mips (and riscv, cribbed from mips). - use db_read_bytes to get instructions - move the address check logic previously attached only to fetching instructions for disassembly to db_read_bytes (and db_write_bytes) Motivated by related x86 changes this afternoon. Note that the address check logic is not as sophisticated as what the x86 code does, but it's what we had before. (Except that riscv will now also try to fetch usermode instructions instead of just failing.)diff -r1.42 -r1.43 src/sys/arch/mips/mips/db_disasm.c
(dholland)
--- src/sys/arch/mips/mips/db_disasm.c 2021/04/12 11:35:22 1.42
+++ src/sys/arch/mips/mips/db_disasm.c 2021/05/23 23:22:55 1.43
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: db_disasm.c,v 1.42 2021/04/12 11:35:22 simonb Exp $ */ | 1 | /* $NetBSD: db_disasm.c,v 1.43 2021/05/23 23:22:55 dholland Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1991, 1993 | 4 | * Copyright (c) 1991, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to Berkeley by | 7 | * This code is derived from software contributed to Berkeley by | |
8 | * Ralph Campbell. | 8 | * Ralph Campbell. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -25,38 +25,39 @@ | @@ -25,38 +25,39 @@ | |||
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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 | * from: @(#)kadb.c 8.1 (Berkeley) 6/10/93 | 34 | * from: @(#)kadb.c 8.1 (Berkeley) 6/10/93 | |
35 | */ | 35 | */ | |
36 | 36 | |||
37 | #include <sys/cdefs.h> | 37 | #include <sys/cdefs.h> | |
38 | __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.42 2021/04/12 11:35:22 simonb Exp $"); | 38 | __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.43 2021/05/23 23:22:55 dholland Exp $"); | |
39 | 39 | |||
40 | #include <sys/param.h> | 40 | #include <sys/param.h> | |
41 | #include <sys/cpu.h> | 41 | #include <sys/cpu.h> | |
42 | #include <sys/systm.h> | 42 | #include <sys/systm.h> | |
43 | 43 | |||
44 | #include <mips/locore.h> | 44 | #include <mips/locore.h> | |
45 | #include <mips/mips_opcode.h> | 45 | #include <mips/mips_opcode.h> | |
46 | #include <mips/reg.h> | 46 | #include <mips/reg.h> | |
47 | 47 | |||
48 | #include <machine/db_machdep.h> | 48 | #include <machine/db_machdep.h> | |
49 | 49 | |||
50 | #include <ddb/db_access.h> | |||
50 | #include <ddb/db_user.h> | 51 | #include <ddb/db_user.h> | |
51 | #include <ddb/db_interface.h> | 52 | #include <ddb/db_interface.h> | |
52 | #include <ddb/db_output.h> | 53 | #include <ddb/db_output.h> | |
53 | #include <ddb/db_extern.h> | 54 | #include <ddb/db_extern.h> | |
54 | #include <ddb/db_sym.h> | 55 | #include <ddb/db_sym.h> | |
55 | 56 | |||
56 | static const char * const op_name[64] = { | 57 | static const char * const op_name[64] = { | |
57 | /* 0 */ "spec", "regimm","j", "jal", "beq", "bne", "blez", "bgtz", | 58 | /* 0 */ "spec", "regimm","j", "jal", "beq", "bne", "blez", "bgtz", | |
58 | /* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui", | 59 | /* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui", | |
59 | /*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl", | 60 | /*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl", | |
60 | /*24 */ "daddi","daddiu","ldl", "ldr", "op34", "op35", "op36", "op37", | 61 | /*24 */ "daddi","daddiu","ldl", "ldr", "op34", "op35", "op36", "op37", | |
61 | /*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "lwu", | 62 | /*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "lwu", | |
62 | /*40 */ "sb", "sh", "swl", "sw", "sdl", "sdr", "swr", "cache", | 63 | /*40 */ "sb", "sh", "swl", "sw", "sdl", "sdr", "swr", "cache", | |
@@ -208,53 +209,43 @@ static const char * const c0_reg[32] = { | @@ -208,53 +209,43 @@ static const char * const c0_reg[32] = { | |||
208 | }; | 209 | }; | |
209 | 210 | |||
210 | static void print_addr(db_addr_t); | 211 | static void print_addr(db_addr_t); | |
211 | 212 | |||
212 | /* | 213 | /* | |
213 | * Disassemble instruction at 'loc'. 'altfmt' specifies an | 214 | * Disassemble instruction at 'loc'. 'altfmt' specifies an | |
214 | * (optional) alternate format (altfmt for vax: don't assume | 215 | * (optional) alternate format (altfmt for vax: don't assume | |
215 | * that each external label is a procedure entry mask). | 216 | * that each external label is a procedure entry mask). | |
216 | * Return address of start of next instruction. | 217 | * Return address of start of next instruction. | |
217 | * Since this function is used by 'examine' and by 'step' | 218 | * Since this function is used by 'examine' and by 'step' | |
218 | * "next instruction" does NOT mean the next instruction to | 219 | * "next instruction" does NOT mean the next instruction to | |
219 | * be executed but the 'linear' next instruction. | 220 | * be executed but the 'linear' next instruction. | |
220 | */ | 221 | */ | |
221 | #ifdef _LP64 | |||
222 | #define DISASM_KERN_START MIPS_XKSEG_START | |||
223 | #else | |||
224 | #define DISASM_KERN_START MIPS_KSEG0_START | |||
225 | #endif | |||
226 | db_addr_t | 222 | db_addr_t | |
227 | db_disasm(db_addr_t loc, bool altfmt) | 223 | db_disasm(db_addr_t loc, bool altfmt) | |
228 | { | 224 | { | |
229 | uint32_t instr; | 225 | uint32_t instr; | |
230 | 226 | |||
231 | /* | 227 | /* | |
232 | * Take some care with addresses to not UTLB here as it | 228 | * Take some care with addresses to not UTLB here as it | |
233 | * loses the current debugging context. KSEG2 and XKSEG | 229 | * loses the current debugging context. KSEG2 and XKSEG | |
234 | * are not checked. | 230 | * are not checked. | |
231 | * Update: db_read_bytes is supposed to do that, and now | |||
232 | * does, so we can use that. | |||
233 | * | |||
234 | * XXX db_read_bytes_can't return failure but instead zeros | |||
235 | * the output. That's ok here, but if ever improved the | |||
236 | * proper thing here on error is to return the original loc. | |||
235 | */ | 237 | */ | |
236 | if (loc < (db_addr_t)DISASM_KERN_START) { | 238 | db_read_bytes(loc, sizeof(instr), (void *)&instr); | |
237 | #ifdef _KERNEL | |||
238 | if (ufetch_32((void *)loc, &instr) != 0) { | |||
239 | db_printf("invalid address.\n"); | |||
240 | return loc; | |||
241 | } | |||
242 | #else | |||
243 | return loc; | |||
244 | #endif | |||
245 | } else { | |||
246 | instr = *(uint32_t *)loc; | |||
247 | } | |||
248 | 239 | |||
249 | return (db_disasm_insn(instr, loc, altfmt)); | 240 | return (db_disasm_insn(instr, loc, altfmt)); | |
250 | } | 241 | } | |
251 | 242 | |||
252 | 243 | |||
253 | /* | 244 | /* | |
254 | * Disassemble instruction 'insn' nominally at 'loc'. | 245 | * Disassemble instruction 'insn' nominally at 'loc'. | |
255 | * 'loc' may in fact contain a breakpoint instruction. | 246 | * 'loc' may in fact contain a breakpoint instruction. | |
256 | */ | 247 | */ | |
257 | db_addr_t | 248 | db_addr_t | |
258 | db_disasm_insn(int insn, db_addr_t loc, bool altfmt) | 249 | db_disasm_insn(int insn, db_addr_t loc, bool altfmt) | |
259 | { | 250 | { | |
260 | bool bdslot = false; | 251 | bool bdslot = false; |
--- src/sys/arch/mips/mips/db_interface.c 2021/04/12 02:23:41 1.93
+++ src/sys/arch/mips/mips/db_interface.c 2021/05/23 23:22:55 1.94
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: db_interface.c,v 1.93 2021/04/12 02:23:41 mrg Exp $ */ | 1 | /* $NetBSD: db_interface.c,v 1.94 2021/05/23 23:22:55 dholland Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Mach Operating System | 4 | * Mach Operating System | |
5 | * Copyright (c) 1991,1990 Carnegie Mellon University | 5 | * Copyright (c) 1991,1990 Carnegie Mellon University | |
6 | * All Rights Reserved. | 6 | * All Rights Reserved. | |
7 | * | 7 | * | |
8 | * Permission to use, copy, modify and distribute this software and its | 8 | * Permission to use, copy, modify and distribute this software and its | |
9 | * documentation is hereby granted, provided that both the copyright | 9 | * documentation is hereby granted, provided that both the copyright | |
10 | * notice and this permission notice appear in all copies of the | 10 | * notice and this permission notice appear in all copies of the | |
11 | * software, derivative works or modified versions, and any portions | 11 | * software, derivative works or modified versions, and any portions | |
12 | * thereof, and that both notices appear in supporting documentation. | 12 | * thereof, and that both notices appear in supporting documentation. | |
13 | * | 13 | * | |
14 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | 14 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
@@ -17,27 +17,27 @@ | @@ -17,27 +17,27 @@ | |||
17 | * | 17 | * | |
18 | * Carnegie Mellon requests users of this software to return to | 18 | * Carnegie Mellon requests users of this software to return to | |
19 | * | 19 | * | |
20 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | 20 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
21 | * School of Computer Science | 21 | * School of Computer Science | |
22 | * Carnegie Mellon University | 22 | * Carnegie Mellon University | |
23 | * Pittsburgh PA 15213-3890 | 23 | * Pittsburgh PA 15213-3890 | |
24 | * | 24 | * | |
25 | * any improvements or extensions that they make and grant Carnegie Mellon | 25 | * any improvements or extensions that they make and grant Carnegie Mellon | |
26 | * the rights to redistribute these changes. | 26 | * the rights to redistribute these changes. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | #include <sys/cdefs.h> | 29 | #include <sys/cdefs.h> | |
30 | __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.93 2021/04/12 02:23:41 mrg Exp $"); | 30 | __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.94 2021/05/23 23:22:55 dholland Exp $"); | |
31 | 31 | |||
32 | #ifdef _KERNEL_OPT | 32 | #ifdef _KERNEL_OPT | |
33 | #include "opt_multiprocessor.h" | 33 | #include "opt_multiprocessor.h" | |
34 | #include "opt_cputype.h" /* which mips CPUs do we support? */ | 34 | #include "opt_cputype.h" /* which mips CPUs do we support? */ | |
35 | #include "opt_ddb.h" | 35 | #include "opt_ddb.h" | |
36 | #include "opt_kgdb.h" | 36 | #include "opt_kgdb.h" | |
37 | #endif | 37 | #endif | |
38 | 38 | |||
39 | #define __PMAP_PRIVATE | 39 | #define __PMAP_PRIVATE | |
40 | 40 | |||
41 | #include <sys/types.h> | 41 | #include <sys/types.h> | |
42 | #include <sys/systm.h> | 42 | #include <sys/systm.h> | |
43 | #include <sys/param.h> | 43 | #include <sys/param.h> | |
@@ -170,51 +170,80 @@ cpu_Debugger(void) | @@ -170,51 +170,80 @@ cpu_Debugger(void) | |||
170 | { | 170 | { | |
171 | 171 | |||
172 | __asm("break"); | 172 | __asm("break"); | |
173 | } | 173 | } | |
174 | #endif /* !KGDB */ | 174 | #endif /* !KGDB */ | |
175 | 175 | |||
176 | /* | 176 | /* | |
177 | * Read bytes from kernel address space for debugger. | 177 | * Read bytes from kernel address space for debugger. | |
178 | */ | 178 | */ | |
179 | void | 179 | void | |
180 | db_read_bytes(vaddr_t addr, size_t size, char *data) | 180 | db_read_bytes(vaddr_t addr, size_t size, char *data) | |
181 | { | 181 | { | |
182 | const char *src = (char *)addr; | 182 | const char *src = (char *)addr; | |
183 | int err; | |||
184 | ||||
185 | /* | |||
186 | * If asked to fetch from userspace, do it safely. | |||
187 | * Note that MIPS_KSEG0_START is the proper address for | |||
188 | * both 32-bit and 64-bit kernels. | |||
189 | */ | |||
190 | if (addr < (vaddr_t)MIPS_KSEG0_START) { | |||
191 | err = copyin(src, data, size); | |||
192 | if (err) { | |||
193 | #ifdef DDB | |||
194 | db_printf("address %p is invalid\n", src); | |||
195 | #endif | |||
196 | memset(data, 0, size); | |||
197 | } | |||
198 | return; | |||
199 | } | |||
183 | 200 | |||
184 | if (size <= 8 && (size & (size-1)) == 0 && (addr & (size-1)) == 0 | 201 | if (size <= 8 && (size & (size-1)) == 0 && (addr & (size-1)) == 0 | |
185 | && ((uintptr_t)data & (size-1)) == 0) { | 202 | && ((uintptr_t)data & (size-1)) == 0) { | |
186 | if (size == sizeof(uint8_t)) | 203 | if (size == sizeof(uint8_t)) | |
187 | *(uint8_t *)data = *(const uint8_t *)src; | 204 | *(uint8_t *)data = *(const uint8_t *)src; | |
188 | else if (size == sizeof(uint16_t)) | 205 | else if (size == sizeof(uint16_t)) | |
189 | *(uint16_t *)data = *(const uint16_t *)src; | 206 | *(uint16_t *)data = *(const uint16_t *)src; | |
190 | else if (size == sizeof(uint32_t)) | 207 | else if (size == sizeof(uint32_t)) | |
191 | *(uint32_t *)data = *(const uint32_t *)src; | 208 | *(uint32_t *)data = *(const uint32_t *)src; | |
192 | else | 209 | else | |
193 | *(uint64_t *)data = *(const uint64_t *)src; | 210 | *(uint64_t *)data = *(const uint64_t *)src; | |
194 | return; | 211 | return; | |
195 | } | 212 | } | |
196 | while (size--) | 213 | while (size--) | |
197 | *data++ = *src++; | 214 | *data++ = *src++; | |
198 | } | 215 | } | |
199 | 216 | |||
200 | /* | 217 | /* | |
201 | * Write bytes to kernel address space for debugger. | 218 | * Write bytes to kernel address space for debugger. | |
202 | */ | 219 | */ | |
203 | void | 220 | void | |
204 | db_write_bytes(vaddr_t addr, size_t size, const char *data) | 221 | db_write_bytes(vaddr_t addr, size_t size, const char *data) | |
205 | { | 222 | { | |
206 | char *p = (char *)addr; | 223 | char *p = (char *)addr; | |
207 | size_t n = size; | 224 | size_t n = size; | |
225 | int err; | |||
226 | ||||
227 | /* If asked to fetch from userspace, do it safely */ | |||
228 | if (addr < (vaddr_t)MIPS_KSEG0_START) { | |||
229 | err = copyout(data, p, size); | |||
230 | if (err) { | |||
231 | #ifdef DDB | |||
232 | db_printf("address %p is invalid\n", p); | |||
233 | #endif | |||
234 | } | |||
235 | return; | |||
236 | } | |||
208 | 237 | |||
209 | if (size <= 8 && (size & (size-1)) == 0 && (addr & (size-1)) == 0 | 238 | if (size <= 8 && (size & (size-1)) == 0 && (addr & (size-1)) == 0 | |
210 | && ((uintptr_t)data & (size-1)) == 0) { | 239 | && ((uintptr_t)data & (size-1)) == 0) { | |
211 | if (size == sizeof(uint8_t)) | 240 | if (size == sizeof(uint8_t)) | |
212 | *(uint8_t *)p = *(const uint8_t *)data; | 241 | *(uint8_t *)p = *(const uint8_t *)data; | |
213 | else if (size == sizeof(uint16_t)) | 242 | else if (size == sizeof(uint16_t)) | |
214 | *(uint16_t *)p = *(const uint16_t *)data; | 243 | *(uint16_t *)p = *(const uint16_t *)data; | |
215 | else if (size == sizeof(uint32_t)) | 244 | else if (size == sizeof(uint32_t)) | |
216 | *(uint32_t *)p = *(const uint32_t *)data; | 245 | *(uint32_t *)p = *(const uint32_t *)data; | |
217 | else | 246 | else | |
218 | *(uint64_t *)p = *(const uint64_t *)data; | 247 | *(uint64_t *)p = *(const uint64_t *)data; | |
219 | return; | 248 | return; | |
220 | } | 249 | } |
--- src/sys/arch/riscv/riscv/db_disasm.c 2021/05/01 06:48:51 1.7
+++ src/sys/arch/riscv/riscv/db_disasm.c 2021/05/23 23:22:55 1.8
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: db_disasm.c,v 1.7 2021/05/01 06:48:51 skrll Exp $ */ | 1 | /* $NetBSD: db_disasm.c,v 1.8 2021/05/23 23:22:55 dholland Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Matt Thomas of 3am Software Foundry. | 8 | * by Matt Thomas of 3am Software Foundry. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -21,34 +21,35 @@ | @@ -21,34 +21,35 @@ | |||
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | 33 | |||
34 | __RCSID("$NetBSD: db_disasm.c,v 1.7 2021/05/01 06:48:51 skrll Exp $"); | 34 | __RCSID("$NetBSD: db_disasm.c,v 1.8 2021/05/23 23:22:55 dholland Exp $"); | |
35 | 35 | |||
36 | #include <sys/param.h> | 36 | #include <sys/param.h> | |
37 | #include <sys/systm.h> | 37 | #include <sys/systm.h> | |
38 | 38 | |||
39 | #include <riscv/db_machdep.h> | 39 | #include <riscv/db_machdep.h> | |
40 | #include <riscv/insn.h> | 40 | #include <riscv/insn.h> | |
41 | 41 | |||
42 | #include <ddb/db_access.h> | |||
42 | #include <ddb/db_user.h> | 43 | #include <ddb/db_user.h> | |
43 | #include <ddb/db_interface.h> | 44 | #include <ddb/db_interface.h> | |
44 | #include <ddb/db_output.h> | 45 | #include <ddb/db_output.h> | |
45 | #include <ddb/db_extern.h> | 46 | #include <ddb/db_extern.h> | |
46 | #include <ddb/db_sym.h> | 47 | #include <ddb/db_sym.h> | |
47 | 48 | |||
48 | //////////////////////////////////////////////////////////// | 49 | //////////////////////////////////////////////////////////// | |
49 | // registers | 50 | // registers | |
50 | 51 | |||
51 | static const char *riscv_registers[32] = { | 52 | static const char *riscv_registers[32] = { | |
52 | "zero", "ra", "sp", "gp", "tp", | 53 | "zero", "ra", "sp", "gp", "tp", | |
53 | "t0", "t1", "t2", | 54 | "t0", "t1", "t2", | |
54 | "s0", "s1", | 55 | "s0", "s1", | |
@@ -1453,43 +1454,36 @@ db_disasm_unknown(const uint16_t *insn, | @@ -1453,43 +1454,36 @@ db_disasm_unknown(const uint16_t *insn, | |||
1453 | db_printf("%02x", insn[i]); | 1454 | db_printf("%02x", insn[i]); | |
1454 | } | 1455 | } | |
1455 | db_printf("\n"); | 1456 | db_printf("\n"); | |
1456 | } | 1457 | } | |
1457 | 1458 | |||
1458 | db_addr_t | 1459 | db_addr_t | |
1459 | db_disasm(db_addr_t loc, bool altfmt) | 1460 | db_disasm(db_addr_t loc, bool altfmt) | |
1460 | { | 1461 | { | |
1461 | /* instructions are up to 5 halfwords */ | 1462 | /* instructions are up to 5 halfwords */ | |
1462 | uint16_t insn[5]; | 1463 | uint16_t insn[5]; | |
1463 | unsigned n, i; | 1464 | unsigned n, i; | |
1464 | uint32_t insn32; | 1465 | uint32_t insn32; | |
1465 | 1466 | |||
1466 | #ifdef _KERNEL | |||
1467 | if ((intptr_t) loc >= 0) { | |||
1468 | db_printf("%s: %#"PRIxVADDR" is not a kernel address\n", | |||
1469 | __func__, loc); | |||
1470 | return loc; | |||
1471 | } | |||
1472 | #endif | |||
1473 | ||||
1474 | /* | 1467 | /* | |
1475 | * Fetch the instruction. The first halfword tells us how many | 1468 | * Fetch the instruction. The first halfword tells us how many | |
1476 | * more there are, and they're always in little-endian order. | 1469 | * more there are, and they're always in little-endian order. | |
1477 | */ | 1470 | */ | |
1478 | insn[0] = ((const uint16_t *)loc)[0]; | 1471 | db_read_bytes(loc, sizeof(insn[0]), (void *)&insn[0]); | |
1479 | n = INSN_HALFWORDS(insn[0]); | 1472 | n = INSN_HALFWORDS(insn[0]); | |
1480 | KASSERT(n > 0 && n <= 5); | 1473 | KASSERT(n > 0 && n <= 5); | |
1481 | for (i = 1; i < n; i++) { | 1474 | for (i = 1; i < n; i++) { | |
1482 | insn[i] = ((const uint16_t *)loc)[i]; | 1475 | db_read_bytes(loc + i * sizeof(insn[i]), sizeof(insn[i]), | |
1476 | (void *)&insn[i]); | |||
1483 | } | 1477 | } | |
1484 | 1478 | |||
1485 | switch (n) { | 1479 | switch (n) { | |
1486 | case 1: | 1480 | case 1: | |
1487 | if (db_disasm_16(loc, insn[0], altfmt) != 0) { | 1481 | if (db_disasm_16(loc, insn[0], altfmt) != 0) { | |
1488 | db_disasm_unknown(insn, n); | 1482 | db_disasm_unknown(insn, n); | |
1489 | } | 1483 | } | |
1490 | break; | 1484 | break; | |
1491 | case 2: | 1485 | case 2: | |
1492 | insn32 = ((uint32_t)insn[1] << 16) | insn[0]; | 1486 | insn32 = ((uint32_t)insn[1] << 16) | insn[0]; | |
1493 | if (db_disasm_32(loc, insn32, altfmt) != 0) { | 1487 | if (db_disasm_32(loc, insn32, altfmt) != 0) { | |
1494 | db_disasm_unknown(insn, n); | 1488 | db_disasm_unknown(insn, n); | |
1495 | } | 1489 | } |
--- src/sys/arch/riscv/riscv/db_machdep.c 2021/04/14 06:32:20 1.7
+++ src/sys/arch/riscv/riscv/db_machdep.c 2021/05/23 23:22:55 1.8
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: db_machdep.c,v 1.7 2021/04/14 06:32:20 dholland Exp $ */ | 1 | /* $NetBSD: db_machdep.c,v 1.8 2021/05/23 23:22:55 dholland Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Matt Thomas of 3am Software Foundry. | 8 | * by Matt Thomas of 3am Software Foundry. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -21,37 +21,38 @@ | @@ -21,37 +21,38 @@ | |||
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | 33 | |||
34 | __RCSID("$NetBSD: db_machdep.c,v 1.7 2021/04/14 06:32:20 dholland Exp $"); | 34 | __RCSID("$NetBSD: db_machdep.c,v 1.8 2021/05/23 23:22:55 dholland Exp $"); | |
35 | 35 | |||
36 | #include <sys/param.h> | 36 | #include <sys/param.h> | |
37 | 37 | |||
38 | #include <riscv/insn.h> | 38 | #include <riscv/insn.h> | |
39 | #include <riscv/db_machdep.h> | 39 | #include <riscv/db_machdep.h> | |
40 | 40 | |||
41 | #include <ddb/db_access.h> | 41 | #include <ddb/db_access.h> | |
42 | #include <ddb/db_interface.h> | 42 | #include <ddb/db_interface.h> | |
43 | #include <ddb/db_extern.h> | 43 | #include <ddb/db_extern.h> | |
44 | #include <ddb/db_variables.h> | 44 | #include <ddb/db_variables.h> | |
45 | #include <ddb/db_output.h> | |||
45 | 46 | |||
46 | int db_active = 0; | 47 | int db_active = 0; | |
47 | 48 | |||
48 | static int db_rw_ddbreg(const struct db_variable *, db_expr_t *, int); | 49 | static int db_rw_ddbreg(const struct db_variable *, db_expr_t *, int); | |
49 | 50 | |||
50 | const struct db_variable db_regs[] = { | 51 | const struct db_variable db_regs[] = { | |
51 | { "ra", (void *)offsetof(struct trapframe, tf_ra), db_rw_ddbreg, NULL }, | 52 | { "ra", (void *)offsetof(struct trapframe, tf_ra), db_rw_ddbreg, NULL }, | |
52 | { "sp", (void *)offsetof(struct trapframe, tf_sp), db_rw_ddbreg, NULL }, | 53 | { "sp", (void *)offsetof(struct trapframe, tf_sp), db_rw_ddbreg, NULL }, | |
53 | { "gp", (void *)offsetof(struct trapframe, tf_gp), db_rw_ddbreg, NULL }, | 54 | { "gp", (void *)offsetof(struct trapframe, tf_gp), db_rw_ddbreg, NULL }, | |
54 | { "tp", (void *)offsetof(struct trapframe, tf_tp), db_rw_ddbreg, NULL }, | 55 | { "tp", (void *)offsetof(struct trapframe, tf_tp), db_rw_ddbreg, NULL }, | |
55 | { "s0", (void *)offsetof(struct trapframe, tf_s0), db_rw_ddbreg, NULL }, | 56 | { "s0", (void *)offsetof(struct trapframe, tf_s0), db_rw_ddbreg, NULL }, | |
56 | { "s1", (void *)offsetof(struct trapframe, tf_s1), db_rw_ddbreg, NULL }, | 57 | { "s1", (void *)offsetof(struct trapframe, tf_s1), db_rw_ddbreg, NULL }, | |
57 | { "s2", (void *)offsetof(struct trapframe, tf_s2), db_rw_ddbreg, NULL }, | 58 | { "s2", (void *)offsetof(struct trapframe, tf_s2), db_rw_ddbreg, NULL }, | |
@@ -215,39 +216,66 @@ branch_taken(uint32_t insn, db_addr_t pc | @@ -215,39 +216,66 @@ branch_taken(uint32_t insn, db_addr_t pc | |||
215 | return pc + displacement; | 216 | return pc + displacement; | |
216 | } | 217 | } | |
217 | 218 | |||
218 | db_addr_t | 219 | db_addr_t | |
219 | next_instr_address(db_addr_t pc, bool bdslot_p) | 220 | next_instr_address(db_addr_t pc, bool bdslot_p) | |
220 | { | 221 | { | |
221 | return pc + (bdslot_p ? 0 : 4); | 222 | return pc + (bdslot_p ? 0 : 4); | |
222 | } | 223 | } | |
223 | 224 | |||
224 | void | 225 | void | |
225 | db_read_bytes(db_addr_t addr, size_t len, char *data) | 226 | db_read_bytes(db_addr_t addr, size_t len, char *data) | |
226 | { | 227 | { | |
227 | const char *src = (char *)addr; | 228 | const char *src = (char *)addr; | |
229 | int err; | |||
230 | ||||
231 | /* If asked to fetch from userspace, do it safely */ | |||
232 | if ((intptr_t)addr >= 0) { | |||
233 | err = copyin(src, data, len); | |||
234 | if (err) { | |||
235 | #ifdef DDB | |||
236 | db_printf("address %p is invalid\n", src); | |||
237 | #endif | |||
238 | memset(data, 0, len); | |||
239 | } | |||
240 | return; | |||
241 | } | |||
228 | 242 | |||
229 | while (len--) { | 243 | while (len--) { | |
230 | *data++ = *src++; | 244 | *data++ = *src++; | |
231 | } | 245 | } | |
232 | } | 246 | } | |
233 | 247 | |||
234 | /* | 248 | /* | |
235 | * Write bytes to kernel address space for debugger. | 249 | * Write bytes to kernel address space for debugger. | |
236 | */ | 250 | */ | |
237 | void | 251 | void | |
238 | db_write_bytes(vaddr_t addr, size_t len, const char *data) | 252 | db_write_bytes(vaddr_t addr, size_t len, const char *data) | |
239 | { | 253 | { | |
254 | int err; | |||
255 | ||||
256 | /* If asked to fetch from userspace, do it safely */ | |||
257 | if ((intptr_t)addr >= 0) { | |||
258 | err = copyout(data, (char *)addr, len); | |||
259 | if (err) { | |||
260 | #ifdef DDB | |||
261 | db_printf("address %p is invalid\n", (char *)addr); | |||
262 | #endif | |||
263 | } | |||
264 | return; | |||
265 | } | |||
266 | ||||
240 | if (len == 8) { | 267 | if (len == 8) { | |
241 | *(uint64_t *)addr = *(const uint64_t *) data; | 268 | *(uint64_t *)addr = *(const uint64_t *) data; | |
242 | } else if (len == 4) { | 269 | } else if (len == 4) { | |
243 | *(uint32_t *)addr = *(const uint32_t *) data; | 270 | *(uint32_t *)addr = *(const uint32_t *) data; | |
244 | } else if (len == 2) { | 271 | } else if (len == 2) { | |
245 | *(uint16_t *)addr = *(const uint16_t *) data; | 272 | *(uint16_t *)addr = *(const uint16_t *) data; | |
246 | } else { | 273 | } else { | |
274 | KASSERT(len == 1); | |||
247 | *(uint8_t *)addr = *(const uint8_t *) data; | 275 | *(uint8_t *)addr = *(const uint8_t *) data; | |
248 | } | 276 | } | |
249 | __asm("fence rw,rw; fence.i"); | 277 | __asm("fence rw,rw; fence.i"); | |
250 | } | 278 | } | |
251 | 279 | |||
252 | 280 | |||
253 | 281 |