]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/alpha/alpha/db_trace.c
This commit was generated by cvs2svn to compensate for changes in r55099,
[FreeBSD/FreeBSD.git] / sys / alpha / alpha / db_trace.c
1 /* $NetBSD: db_trace.c,v 1.1 1997/09/06 02:00:50 thorpej Exp $ */
2
3 #include <sys/cdefs.h>                  /* RCS ID & Copyright macro defns */
4
5 /* __KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.1 1997/09/06 02:00:50 thorpej Exp $"); */
6
7 #include <sys/param.h>
8 #include <sys/proc.h>
9 #include <machine/db_machdep.h>
10
11 #include <ddb/ddb.h>
12 #include <ddb/db_sym.h> 
13 #include <ddb/db_access.h>
14 #include <ddb/db_variables.h>
15 #include <ddb/db_output.h>
16 #include <alpha/alpha/db_instruction.h>
17
18 struct alpha_proc {
19         int             pcreg;          /* index of return pc register */
20         int             frame_size;     /* size of stack frame */
21         u_int32_t       reg_mask;
22         int             regs[32];       /* offsets from sp to saved regs */
23 };
24
25 static void
26 parse_proc(db_expr_t addr, struct alpha_proc* frame)
27 {
28         c_db_sym_t sym;
29         db_expr_t func;
30         db_expr_t junk, pc, limit;
31
32         frame->pcreg = -1;
33         frame->reg_mask = 0;
34         frame->frame_size = 0;
35
36         sym = db_search_symbol(addr, DB_STGY_PROC, &junk);
37         if (!sym)
38                 return;
39         db_symbol_values(sym, 0, &func);
40
41         pc = func;
42         limit = addr;
43         if (limit - pc > 200)
44                 limit = pc + 200;
45         for (; pc < limit; pc += 4) {
46                 alpha_instruction ins;
47                 ins.bits = *(u_int32_t*) pc;
48                 if (ins.memory_format.opcode == op_lda
49                     && ins.memory_format.ra == 30) {
50                         /* gcc 2.7 */
51                         frame->frame_size += -ins.memory_format.offset;
52                 } else if (ins.operate_lit_format.opcode == op_arit
53                     && ins.operate_lit_format.function == op_subq
54                     && ins.operate_lit_format.rs == 30) {
55                         /* egcs */
56                         frame->frame_size += ins.operate_lit_format.literal;
57                 } else if (ins.memory_format.opcode == op_stq
58                            && ins.memory_format.rb == 30
59                            && ins.memory_format.ra != 31) {
60                         int reg = ins.memory_format.ra;
61                         frame->reg_mask |= 1 << reg;
62                         frame->regs[reg] = ins.memory_format.offset;
63                         if (frame->pcreg == -1 && reg == 26)
64                                 frame->pcreg = reg;
65                 }
66         }
67 }
68
69 void
70 db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *modif)
71 {
72         db_addr_t callpc;
73         db_addr_t frame;
74
75         if (count == -1)
76                 count = 65535;
77
78         if (!have_addr) {
79                 frame = (db_addr_t) ddb_regs.tf_regs[FRAME_SP];
80                 callpc = (db_addr_t)ddb_regs.tf_regs[FRAME_PC];
81         } else {
82                 frame = (db_addr_t)addr;
83                 callpc = (db_addr_t)db_get_value(frame, 8, FALSE);
84         }
85
86         while (count--) {
87                 const char *    name;
88                 db_expr_t       offset;
89                 c_db_sym_t      sym;
90                 struct alpha_proc proc;
91
92                 sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
93                 db_symbol_values(sym, &name, NULL);
94
95                 db_printf("%s() at ", name);
96                 db_printsym(callpc, DB_STGY_PROC);
97                 db_printf("\n");
98
99                 parse_proc(callpc, &proc);
100
101                 if (proc.pcreg == -1)
102                         break;
103
104                 callpc = db_get_value(frame + proc.regs[proc.pcreg], 8, FALSE);
105                 frame = frame + proc.frame_size;
106         }
107 }