Subject: kern/1294: GDB can kinda debug kernels and crashes
To: None <gnats-bugs@gnats.netbsd.org>
From: James Jegers <jimj@miller.cs.uwm.edu>
List: netbsd-bugs
Date: 07/28/1995 13:10:50
>Number:         1294
>Category:       kern
>Synopsis:       GDB almost works on kernels
>Confidential:   yes
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Fri Jul 28 14:20:00 1995
>Last-Modified:
>Originator:     James Jegers
>Organization:

>Release:        Current as of Jul 5<NetBSD-current source date>
>Environment:

System: NetBSD jimj.home.edu 1.0A NetBSD 1.0A (JIMJ) #4: Fri Jul 28 09:42:32 CDT 1995 jimj@jimj.home.edu:/usr/src/sys/arch/i386/compile/JIMJ i386

>Description:
	After wanting a better debugger for the kernel for some time.  I really
	started playing with it and kinda got it to work.
	There are two sets of patches here, one is for the gdb to make it
	read in a kernel panic/crash file or the live kernel.  I'm still having
	problems getting the stack output to look ok.  sometimes it works and
	sometimes it doesn't.  I'm not sure if we ever can get the correct
	information..???
	The other patch is to the kernel to allow user programs to read the
	kernel stack from /dev/kmem.  currently access is denied.  I'm not
	sure if this fix is the correct way to do it.  It looks like the i386
	port is in flux.

>How-To-Repeat:

>Fix:

diff -c2 ../../gdb/gdb/kcorelow.c ./kcorelow.c
*** ../../gdb/gdb/kcorelow.c	Tue Jul 25 21:02:28 1995
--- ./kcorelow.c	Fri Jul 28 08:57:54 1995
***************
*** 70,75 ****
  		error("cannot read proc pointer at %x\n", addr);
  
! 	if (p == NULL)
  		p = (struct proc *)ksym_lookup("proc0");
  
  	return p;
--- 91,100 ----
  		error("cannot read proc pointer at %x\n", addr);
  
! 
!         if (p == NULL)
! 	{
! 		printf("curproc is NULL, using proc0\n");
  		p = (struct proc *)ksym_lookup("proc0");
+ 	}
  
  	return p;
***************
*** 222,236 ****
  	struct user *uaddr;
  	struct pcb pcb;
  
- 	/* find the pcb for the current process */
- 	if (kvread(&cur_proc->p_addr, &uaddr))
- 		error("cannot read u area ptr for proc at %#x", cur_proc);
- 	if (kvread(&uaddr->u_pcb, &pcb))
- 		error("cannot read pcb at %#x", &uaddr->u_pcb);
  	/*
  	 * Zero out register set then fill in the ones we know about.
  	 */
  	clear_regs();
! 	fetch_kcore_registers (&pcb);
  }
  
--- 247,280 ----
  	struct user *uaddr;
  	struct pcb pcb;
+ 	CORE_ADDR addr;
+ 
+ 	/* This might be a crash dump, if so the vital information
+ 	** appears to be stored in the dumppcb variable.  Take a look at
+ 	** it and see if it contains anything good looking.
+ 	*/
+ 	addr = ksym_lookup("dumppcb");
+ 	if (kvread(addr, &pcb))
+ 		error("cannot read dumpsys pcb at 0x%x", addr);
+ 
+ 	/* the esp register gets filled in during a dump.  If it is 
+ 	** 0 then it probably hasn't been filled in and we are looking
+ 	** at a live kernel, or something else?
+ 	*/
+ 	if (pcb.pcb_tss.tss_esp == 0)
+ 	{
+ 		/* find the pcb for the current process */
+ 		if (kvread(&cur_proc->p_addr, &uaddr))
+ 			error("cannot read u area ptr for proc at 0x%x", 
+ 			    cur_proc);
+ 
+ 		if (kvread(&uaddr->u_pcb, &pcb))
+ 			error("cannot read pcb at %#x", &uaddr->u_pcb);
+ 	}
  
  	/*
  	 * Zero out register set then fill in the ones we know about.
  	 */
  	clear_regs();
! 	fetch_kcore_registers (&pcb); 
  }
  
diff -c2 ../../gdb/gdb/arch/i386/i386b-nat.c arch/i386/i386b-nat.c
*** ../../gdb/gdb/arch/i386/i386b-nat.c	Wed Jun 14 11:39:44 1995
--- arch/i386/i386b-nat.c	Thu Jul 27 14:44:46 1995
***************
*** 31,34 ****
--- 31,35 ----
  #include "defs.h"
  #include "inferior.h"
+ #include "target.h"
  
  int tregmap[] = {tEAX, tECX, tEDX, tEBX, tESP, tEBP, tESI, tEDI,
***************
*** 316,329 ****
           * store them where `read_register' will find them.
           */
! 	if (target_read_memory(pcb->pcb_tss.tss_esp+4, regs, sizeof regs, 0))
  		error("Cannot read ebx, esi, and edi.");
  	for (i = 0, regno = 0; regno < 3; regno++)
  		supply_register(regno, &i);
! 	supply_register(3, &regs[2]);
! 	supply_register(4, &pcb->pcb_tss.tss_esp);
! 	supply_register(5, &pcb->pcb_tss.tss_ebp);
! 	supply_register(6, &regs[1]);
! 	supply_register(7, &regs[0]);
! 	supply_register(8, &regs[3]);
  	for (i = 0, regno = 9; regno < 10; regno++)
  		supply_register(regno, &i);
--- 317,347 ----
           * store them where `read_register' will find them.
           */
! 
! 	printf("fetch_kcore_registers() esp 0x%x, ebp 0x%x\n", 
! 		pcb->pcb_tss.tss_esp, pcb->pcb_tss.tss_ebp);
! 
! 	/* I don't really understand things here.  If this crash was
! 	** done during a reboot/panic the ebx,esi,edi registers will
! 	** be whiped out when the next function is called..
! 	*/
! 
! 	/* I'm still not sure what location to find the PC(eip?) in.
! 	** So far ebp+4 seems to be a good location, at least gdb
! 	** will do something.. help!
! 	*/
! 	if (target_read_memory((pcb->pcb_tss.tss_ebp)+4, regs, sizeof(regs) ))
  		error("Cannot read ebx, esi, and edi.");
+ 
+ 	/* Zero out all the registers */
  	for (i = 0, regno = 0; regno < 3; regno++)
  		supply_register(regno, &i);
! 
! 	/*supply_register(3, &regs[2]);*/
! 	supply_register(4, &(pcb->pcb_tss.tss_esp));
! 	supply_register(5, &(pcb->pcb_tss.tss_ebp));
! 	/*supply_register(6, &regs[1]);*/
! 	/*supply_register(7, &regs[0]);*/
! 	supply_register(8, &regs[0]);
! 
  	for (i = 0, regno = 9; regno < 10; regno++)
  		supply_register(regno, &i);

*** vm_glue.c.old	Fri Jul 28 10:07:03 1995
--- vm_glue.c	Fri Jul 28 09:41:20 1995
***************
*** 90,93 ****
--- 90,101 ----
  	vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE;
  
+ #if defined(i386)
+ 	/* If we are looking at the stack, let it be, otherwise use
+ 	** the old routines to check 
+ 	*/
+ 	if ((vm_offset_t)addr >= VM_MAXUSER_ADDRESS && 
+ 	    (vm_offset_t)addr+len < VM_MAX_ADDRESS)
+ 		return(TRUE);
+ #endif
  	saddr = trunc_page(addr);
  	eaddr = round_page(addr+len);

>Audit-Trail:
>Unformatted: