Annotation of src/sys/arch/amd64/amd64/db_machdep.c, Revision 1.2
1.2 ! chs 1: /* $NetBSD: db_machdep.c,v 1.1 2011/04/10 20:36:49 christos Exp $ */
1.1 christos 2:
3: /*
4: * Mach Operating System
5: * Copyright (c) 1991,1990 Carnegie Mellon University
6: * All Rights Reserved.
7: *
8: * Permission to use, copy, modify and distribute this software and its
9: * documentation is hereby granted, provided that both the copyright
10: * notice and this permission notice appear in all copies of the
11: * software, derivative works or modified versions, and any portions
12: * thereof, and that both notices appear in supporting documentation.
13: *
14: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17: *
18: * Carnegie Mellon requests users of this software to return to
19: *
20: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21: * School of Computer Science
22: * Carnegie Mellon University
23: * Pittsburgh PA 15213-3890
24: *
25: * any improvements or extensions that they make and grant Carnegie the
26: * rights to redistribute these changes.
27: */
28: #include <sys/cdefs.h>
1.2 ! chs 29: __KERNEL_RCSID(0, "$NetBSD: db_machdep.c,v 1.1 2011/04/10 20:36:49 christos Exp $");
1.1 christos 30:
31: #include <sys/param.h>
32: #include <sys/systm.h>
33: #include <sys/proc.h>
34:
35: #include <machine/frame.h>
36: #include <machine/trap.h>
37: #include <machine/intrdefs.h>
38:
39: #include <machine/db_machdep.h>
40: #include <ddb/db_sym.h>
41: #include <ddb/db_access.h>
42: #include <ddb/db_variables.h>
43: #include <ddb/db_output.h>
44: #include <ddb/db_interface.h>
45: #include <ddb/db_user.h>
46: #include <ddb/db_proc.h>
47: #include <ddb/db_command.h>
48: #include <x86/db_machdep.h>
49:
50: #define dbreg(xx) (long *)offsetof(db_regs_t, tf_ ## xx)
51:
52: /*
53: * Machine register set.
54: */
55: const struct db_variable db_regs[] = {
56: { "ds", dbreg(ds), db_x86_regop, NULL },
57: { "es", dbreg(es), db_x86_regop, NULL },
58: { "fs", dbreg(fs), db_x86_regop, NULL },
59: { "gs", dbreg(gs), db_x86_regop, NULL },
60: { "rdi", dbreg(rdi), db_x86_regop, NULL },
61: { "rsi", dbreg(rsi), db_x86_regop, NULL },
62: { "rbp", dbreg(rbp), db_x86_regop, NULL },
63: { "rbx", dbreg(rbx), db_x86_regop, NULL },
64: { "rdx", dbreg(rdx), db_x86_regop, NULL },
65: { "rcx", dbreg(rcx), db_x86_regop, NULL },
66: { "rax", dbreg(rax), db_x86_regop, NULL },
67: { "r8", dbreg(r8), db_x86_regop, NULL },
68: { "r9", dbreg(r9), db_x86_regop, NULL },
69: { "r10", dbreg(r10), db_x86_regop, NULL },
70: { "r11", dbreg(r11), db_x86_regop, NULL },
71: { "r12", dbreg(r12), db_x86_regop, NULL },
72: { "r13", dbreg(r13), db_x86_regop, NULL },
73: { "r14", dbreg(r14), db_x86_regop, NULL },
74: { "r15", dbreg(r15), db_x86_regop, NULL },
75: { "rip", dbreg(rip), db_x86_regop, NULL },
76: { "cs", dbreg(cs), db_x86_regop, NULL },
77: { "rflags", dbreg(rflags), db_x86_regop, NULL },
78: { "rsp", dbreg(rsp), db_x86_regop, NULL },
79: { "ss", dbreg(ss), db_x86_regop, NULL },
80: };
81: const struct db_variable * const db_eregs =
82: db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
83:
84: /*
85: * Figure out how many arguments were passed into the frame at "fp".
86: * We can probably figure out how many arguments where passed above
87: * the first 6 (which are in registers), but since we can't
88: * reliably determine the values currently, just return 0.
89: */
90: int
91: db_numargs(long *retaddrp)
92: {
93: return 0;
94: }
95:
96: /*
97: * Figure out the next frame up in the call stack.
98: * For trap(), we print the address of the faulting instruction and
99: * proceed with the calling frame. We return the ip that faulted.
100: * If the trap was caused by jumping through a bogus pointer, then
101: * the next line in the backtrace will list some random function as
102: * being called. It should get the argument list correct, though.
103: * It might be possible to dig out from the next frame up the name
104: * of the function that faulted, but that could get hairy.
105: */
106: int
107: db_nextframe(long **nextframe, long **retaddr, long **arg0, db_addr_t *ip,
108: long *argp, int is_trap, void (*pr)(const char *, ...))
109: {
110: struct trapframe *tf;
111: struct x86_64_frame *fp;
112: struct intrframe *ifp;
113: int traptype, trapno, err, i;
114:
115: switch (is_trap) {
116: case NONE:
117: *ip = (db_addr_t)
118: db_get_value((long)*retaddr, 8, false);
119: fp = (struct x86_64_frame *)
120: db_get_value((long)*nextframe, 8, false);
121: if (fp == NULL)
122: return 0;
123: *nextframe = (long *)&fp->f_frame;
124: *retaddr = (long *)&fp->f_retaddr;
125: *arg0 = (long *)&fp->f_arg0;
126: break;
127:
128: case TRAP:
129: case SYSCALL:
130: case INTERRUPT:
131: default:
132:
133: /* The only argument to trap() or syscall() is the trapframe. */
1.2 ! chs 134: tf = (struct trapframe *)argp;
1.1 christos 135: switch (is_trap) {
136: case TRAP:
137: (*pr)("--- trap (number %d) ---\n", tf->tf_trapno);
138: break;
139: case SYSCALL:
140: (*pr)("--- syscall (number %ld) ---\n", tf->tf_rax);
141: break;
142: case INTERRUPT:
143: (*pr)("--- interrupt ---\n");
144: break;
145: }
146: *ip = (db_addr_t)tf->tf_rip;
147: fp = (struct x86_64_frame *)tf->tf_rbp;
148: if (fp == NULL)
149: return 0;
150: *nextframe = (long *)&fp->f_frame;
151: *retaddr = (long *)&fp->f_retaddr;
152: *arg0 = (long *)&fp->f_arg0;
153: break;
154: }
155:
156: /*
157: * A bit of a hack. Since %rbp may be used in the stub code,
158: * walk the stack looking for a valid interrupt frame. Such
159: * a frame can be recognized by always having
160: * err 0 or IREENT_MAGIC and trapno T_ASTFLT.
161: */
162: if (db_frame_info(*nextframe, (db_addr_t)*ip, NULL, NULL, &traptype,
163: NULL) != (db_sym_t)0
164: && traptype == INTERRUPT) {
165: for (i = 0; i < 4; i++) {
166: ifp = (struct intrframe *)(argp + i);
167: err = db_get_value((long)&ifp->if_tf.tf_err,
168: sizeof(long), false);
169: trapno = db_get_value((long)&ifp->if_tf.tf_trapno,
170: sizeof(long), false);
171: if ((err == 0 || err == IREENT_MAGIC)
172: && trapno == T_ASTFLT) {
173: *nextframe = (long *)ifp - 1;
174: break;
175: }
176: }
177: if (i == 4) {
178: (*pr)("DDB lost frame for ");
179: db_printsym(*ip, DB_STGY_ANY, pr);
180: (*pr)(", trying %p\n",argp);
181: *nextframe = argp;
182: }
183: }
184: return 1;
185: }
186:
187: db_sym_t
188: db_frame_info(long *frame, db_addr_t callpc, const char **namep,
189: db_expr_t *offp, int *is_trap, int *nargp)
190: {
191: db_expr_t offset;
192: db_sym_t sym;
193: int narg;
194: const char *name;
195:
196: sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
197: db_symbol_values(sym, &name, NULL);
198: if (sym == (db_sym_t)0)
199: return (db_sym_t)0;
200:
201: *is_trap = NONE;
202: narg = 0;
203:
204: if (INKERNEL((long)frame) && name) {
205: /*
206: * XXX traps should be based off of the Xtrap*
207: * locations rather than on trap, since some traps
208: * (e.g., npxdna) don't go through trap()
209: */
210: if (!strcmp(name, "trap")) {
211: *is_trap = TRAP;
212: narg = 0;
213: } else if (!strcmp(name, "syscall_plain") ||
214: !strcmp(name, "syscall_fancy")) {
215: *is_trap = SYSCALL;
216: narg = 0;
217: } else if (name[0] == 'X') {
218: if (!strncmp(name, "Xintr", 5) ||
219: !strncmp(name, "Xresume", 7) ||
220: !strncmp(name, "Xstray", 6) ||
221: !strncmp(name, "Xhold", 5) ||
222: !strncmp(name, "Xrecurse", 8) ||
223: !strcmp(name, "Xdoreti") ||
224: !strncmp(name, "Xsoft", 5)) {
225: *is_trap = INTERRUPT;
226: narg = 0;
227: }
228: }
229: }
230:
231: if (offp != NULL)
232: *offp = offset;
233: if (nargp != NULL)
234: *nargp = narg;
235: if (namep != NULL)
236: *namep = name;
237: return sym;
238: }
CVSweb <webmaster@jp.NetBSD.org>