⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 db_trace.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
字号:
/*	$NetBSD: db_trace.c,v 1.17 1995/10/11 04:19:35 mycroft Exp $	*//*  * Mach Operating System * Copyright (c) 1991,1990 Carnegie Mellon University * All Rights Reserved. *  * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. *  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. *  * Carnegie Mellon requests users of this software to return to *  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU *  School of Computer Science *  Carnegie Mellon University *  Pittsburgh PA 15213-3890 *  * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */#include <arch-kerninc/db_machdep.hxx>#include <ddb/db_access.hxx>#include <ddb/db_sym.hxx>#include <ddb/db_variables.hxx>#include <ddb/db_output.hxx>#include <kerninc/util.h>extern bool db_sym_numargs(db_sym_t sym, int *nargp, const char **argnames);/* * Machine register set. */struct db_variable db_regs[] = {  { "es",	  (long *)&ddb_regs.ES,     FCN_NULL, false },  { "ds",	  (long *)&ddb_regs.DS,     FCN_NULL, false },  { "edi",	  (long *)&ddb_regs.EDI,    FCN_NULL, true },  { "esi",	  (long *)&ddb_regs.ESI,    FCN_NULL, true },  { "ebp",	  (long *)&ddb_regs.EBP,    FCN_NULL, true },  { "ebx",	  (long *)&ddb_regs.EBX,    FCN_NULL, true },  { "edx",	  (long *)&ddb_regs.EDX,    FCN_NULL, true },  { "ecx",	  (long *)&ddb_regs.ECX,    FCN_NULL, true },  { "eax",	  (long *)&ddb_regs.EAX,    FCN_NULL, true },  { "eip",	  (long *)&ddb_regs.EIP,    FCN_NULL, true },  { "cs",	  (long *)&ddb_regs.CS,     FCN_NULL, true },  { "eflags",     (long *)&ddb_regs.EFLAGS, FCN_NULL, false },  { "esp",	  (long *)&ddb_regs.ESP,    FCN_NULL, false },  { "ss",	  (long *)&ddb_regs.SS,     FCN_NULL, false } ,};struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);/* * Stack trace. */#define EIP_INBIOS(eip) (eip >= 0xe0000u && eip < 0xfffff)#define EIP_INKTEXT(eip) (eip >= (u_long)_start && eip < (u_long)etext)#define EIP_INKERNEL(eip) (EIP_INKTEXT(eip) || EIP_INBIOS(eip))#define KERNEL_TRAP(frame) EIP_INKERNEL(((fixregs_t *)frame)->EIP)			 extern "C" {  extern char _start[];  extern char etext[];}struct i386_frame {	struct i386_frame	*f_frame;	int			f_retaddr;	int			f_arg0;};#define	NONE		0#define	TRAP		1#define	SYSCALL		2#define	INTERRUPT	3db_addr_t	db_trap_symbol_value = 0;db_addr_t	db_syscall_symbol_value = 0;db_addr_t	db_kdintr_symbol_value = 0;bool	db_trace_symbols_found = false;voiddb_find_trace_symbols(){	db_expr_t	value;	if (db_value_of_name("_trap", &value))		db_trap_symbol_value = (db_addr_t) value;	if (db_value_of_name("_kdintr", &value))		db_kdintr_symbol_value = (db_addr_t) value;	if (db_value_of_name("_syscall", &value))		db_syscall_symbol_value = (db_addr_t) value;	db_trace_symbols_found = true;}/* * Figure out how many arguments were passed into the frame at "fp". */intdb_numargs(struct i386_frame * /* fp */){#if 0	int	*argp;	int	inst;	int	args;	extern char	etext[];	argp = (int *)db_get_value((int)&fp->f_retaddr, 4, false);	if (argp < (int *)VM_MIN_KERNEL_ADDRESS || argp > (int *)etext) {		args = 5;	} else {		inst = db_get_value((int)argp, 4, false);		if ((inst & 0xff) == 0x59)	/* popl %ecx */			args = 1;		else if ((inst & 0xffff) == 0xc483)	/* addl %n, %esp */			args = ((inst >> 16) & 0xff) / 4;		else			args = 5;	}	return (args);#else	return 0;#endif}/*  * Figure out the next frame up in the call stack.   * For trap(), we print the address of the faulting instruction and  *   proceed with the calling frame.  We return the ip that faulted. *   If the trap was caused by jumping through a bogus pointer, then *   the next line in the backtrace will list some random function as  *   being called.  It should get the argument list correct, though.   *   It might be possible to dig out from the next frame up the name *   of the function that faulted, but that could get hairy. */voiddb_nextframe(struct i386_frame **fp, /* in/out */	     db_addr_t *ip,	/* out */	     int *argp,		/* in */	     int is_trap	/* in */	     ){	switch (is_trap) {	    case NONE:		*ip = (db_addr_t)			db_get_value((int) &(*fp)->f_retaddr, 4, false);		*fp = (struct i386_frame *)			db_get_value((int) &(*fp)->f_frame, 4, false);		break;	    default: {		struct fixregs_t *tf; /* trap frame */		/* The only argument to trap() or syscall() is the trapframe. */		tf = * ((struct fixregs_t **)argp);/* on EROS, the */						  /* trapframe ptr */		const char *trap_mode = KERNEL_TRAP(tf) ? "kernel" : "user";				switch (is_trap) {		case TRAP:		  db_printf("--- %s trap (EIP=0x%08x vector=0x%x sa=0x%08x) ---\n",			    trap_mode, tf->EIP, tf->ExceptNo, tf);		  break;		case SYSCALL:		  db_printf("--- %s IPC (EIP=0x%08x OC=%d sa=0x%08x) ---\n",			    trap_mode, tf->EIP, tf->EAX, tf);		  break;#if 0		case INTERRUPT:			db_printf("--- interrupt ---\n");			break;#endif		}		*fp = (struct i386_frame *)tf->EBP;		*ip = (db_addr_t)tf->EIP;		if ( !KERNEL_TRAP(tf) )		  *fp = 0;		    		break;	    }	}}voiddb_stack_trace_cmd(db_expr_t addr, int have_addr,		   db_expr_t count, char *modif){  struct i386_frame *frame, *lastframe;#if 0  int		*argp = 0;#endif  db_addr_t	callpc;  int		is_trap = 0;  bool	kernel_only = true;  bool	trace_thread = false;#if 0  if (!db_trace_symbols_found)    db_find_trace_symbols();#endif  {    register char *cp = modif;    register char c;    while ((c = *cp++) != 0) {      if (c == 't')	trace_thread = true;      if (c == 'u')	kernel_only = false;    }  }  if (count == -1)    count = 65535;  if (!have_addr) {    frame = (struct i386_frame *)ddb_regs.EBP;    callpc = (db_addr_t)ddb_regs.EIP;  } else if (trace_thread) {    db_printf ("db_trace.c: can't trace thread\n");  } else {    frame = (struct i386_frame *)addr;    callpc = (db_addr_t)      db_get_value((int)&frame->f_retaddr, 4, false);  }  lastframe = 0;  while (count && frame != 0) {    int		narg;    const char *	name;    db_expr_t	offset;    db_sym_t	sym;#define MAXNARG	16    const char	*argnames[MAXNARG], **argnp = NULL;    sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);    db_symbol_values(sym, &name, NULL);    if (lastframe == 0 && sym == NULL) {      /* Symbol not found, peek at code */      int	instr = db_get_value(callpc, 4, false);      offset = 1;      if ((instr & 0x00ffffff) == 0x00e58955 ||	  /* enter: pushl %ebp, movl %esp, %ebp */	  (instr & 0x0000ffff) == 0x0000e589	  /* enter+1: movl %esp, %ebp */) {	offset = 0;      }    }    if (name) {#if 0      db_printf("%s\n", name);#endif      if (!strcmp(name,		  "IDT::OnTrapOrInterrupt(fixregs_t *)")) {	is_trap = TRAP;      }      else if (!strcmp(name,		       "IDT::OnKeyInvocationTrap(fixregs_t *)")) {	is_trap = SYSCALL;      }      else if (!strcmp(name,		       "LowYield")) {	db_printf("--- Yield ---\n");	return;      }#if 0      else if (!strcmp(name, "intr_clock")) {	is_trap = TRAP;      }      else if (!strcmp(name, "intr_InvokeKey")) {	is_trap = TRAP;      }      else if (!strcmp(name, "int_CapInstr")) {	is_trap = TRAP;      }      if (!strcmp(name, "_trap")) {	is_trap = TRAP;      } else if (!strcmp(name, "_syscall")) {	is_trap = SYSCALL;      } else if (name[0] == '_' && name[1] == 'X') {	if (!strncmp(name, "_Xintr", 6) ||	    !strncmp(name, "_Xresume", 8) ||	    !strncmp(name, "_Xstray", 7) ||	    !strncmp(name, "_Xhold", 6) ||	    !strncmp(name, "_Xrecurse", 9) ||	    !strcmp(name, "_Xdoreti") ||	    !strncmp(name, "_Xsoft", 6)) {	  is_trap = INTERRUPT;	} else	  goto normal;      }#endif      else	goto normal;      narg = 0;    } else {    normal:      is_trap = NONE;      narg = MAXNARG;      if (db_sym_numargs(sym, &narg, argnames))	argnp = argnames;      else	narg = db_numargs(frame);    }#if 0    db_printf("%s(", name);    if (lastframe == 0 && offset == 0 && !have_addr) {      /*       * We have a breakpoint before the frame is set up       * Use %esp instead       */      argp = &((struct i386_frame *)(ddb_regs.ESP-4))->f_arg0;    } else {      argp = &frame->f_arg0;    }    while (narg) {      if (argnp)	db_printf("%s=", *argnp++);      db_printf("%x", db_get_value((int)argp, 4, false));      argp++;      if (--narg != 0)	db_printf(",");    }    db_printf(") at ");#endif    db_printf("0x%08x: [FP=0x%08x] ", callpc, frame);    db_printsym(callpc, DB_STGY_PROC);    db_printf("\n");    if (lastframe == 0 && offset == 0 && !have_addr) {      /* Frame really belongs to next callpc */      lastframe = (struct i386_frame *)(ddb_regs.ESP-4);      callpc = (db_addr_t)	db_get_value((int)&lastframe->f_retaddr, 4, false);#if 0      db_printf("Next frame call pc: 0x%08x is_trap=%d\n",		callpc, is_trap);#endif      continue;    }    lastframe = frame;    db_nextframe(&frame, &callpc, &frame->f_arg0, is_trap);#if 0    db_printf("db_nextframe() => callpc 0x%08x frame 0x%08x"	      " is_trap %d\n",	      callpc, frame, is_trap);#endif    if (frame == 0) {      /* end of chain */      break;    }    --count;  }#if 0  if (count && is_trap != NONE) {    db_printsym(callpc, DB_STGY_XTRN);    db_printf(":\n");  }#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -