/* $NetBSD: db_trace.c,v 1.1 1997/09/06 02:00:50 thorpej Exp $ */ #include /* RCS ID & Copyright macro defns */ /* __KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.1 1997/09/06 02:00:50 thorpej Exp $"); */ #include #include #include #include #include #include #include #include #include struct alpha_proc { int pcreg; /* index of return pc register */ int frame_size; /* size of stack frame */ u_int32_t reg_mask; int regs[32]; /* offsets from sp to saved regs */ }; static void parse_proc(db_expr_t addr, struct alpha_proc* frame) { c_db_sym_t sym; db_expr_t func; db_expr_t junk, pc, limit; frame->pcreg = -1; frame->reg_mask = 0; frame->frame_size = 0; sym = db_search_symbol(addr, DB_STGY_PROC, &junk); if (!sym) return; db_symbol_values(sym, 0, &func); pc = func; limit = addr; if (limit - pc > 200) limit = pc + 200; for (; pc < limit; pc += 4) { alpha_instruction ins; ins.bits = *(u_int32_t*) pc; if (ins.memory_format.opcode == op_lda && ins.memory_format.ra == 30) { /* gcc 2.7 */ frame->frame_size += -ins.memory_format.offset; } else if (ins.operate_lit_format.opcode == op_arit && ins.operate_lit_format.function == op_subq && ins.operate_lit_format.rs == 30) { /* egcs */ frame->frame_size += ins.operate_lit_format.literal; } else if (ins.memory_format.opcode == op_stq && ins.memory_format.rb == 30 && ins.memory_format.ra != 31) { int reg = ins.memory_format.ra; frame->reg_mask |= 1 << reg; frame->regs[reg] = ins.memory_format.offset; if (frame->pcreg == -1 && reg == 26) frame->pcreg = reg; } } } void db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count, char *modif) { db_addr_t callpc; db_addr_t frame; if (count == -1) count = 65535; if (!have_addr) { frame = (db_addr_t) ddb_regs.tf_regs[FRAME_SP]; callpc = (db_addr_t)ddb_regs.tf_regs[FRAME_PC]; } else { frame = (db_addr_t)addr; callpc = (db_addr_t)db_get_value(frame, 8, FALSE); } while (count--) { const char * name; db_expr_t offset; c_db_sym_t sym; struct alpha_proc proc; sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); db_symbol_values(sym, &name, NULL); db_printf("%s() at ", name); db_printsym(callpc, DB_STGY_PROC); db_printf("\n"); parse_proc(callpc, &proc); if (proc.pcreg == -1) break; callpc = db_get_value(frame + proc.regs[proc.pcreg], 8, FALSE); frame = frame + proc.frame_size; } }