Apply an iffy heuristic to detect a valid switchframe on the stack and

extract the register state from this for the live kernel case. If there
is no switchframe then use the frame pointer to get enough state for crash
dump case.

More information needs to be saved by savectx to avoid this mess.

Should fix PR/35118
This commit is contained in:
skrll 2007-01-18 18:15:02 +00:00
parent 089d34fd42
commit ba85386518

View File

@ -41,33 +41,58 @@ i386nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
{
struct switchframe sf;
/* The following is true for NetBSD 1.6.2:
/* The following is true for NetBSD 1.6.2 and after:
The pcb contains %esp and %ebp at the point of the context switch
in cpu_switch(). At that point we have a stack frame as
described by `struct switchframe', which for NetBSD 1.6.2 has the
described by `struct switchframe', which for NetBSD has the
following layout:
interrupt level
%edi
%esi
%ebx
%eip
return address
we reconstruct the register state as it would look when we just
returned from cpu_switch(). */
returned from cpu_switch().
For core dumps the pcb is saved by savectx() and contains the
stack pointer and frame pointer. In this case extract a return
address from the stack. */
/* The stack pointer shouldn't be zero. */
if (pcb->pcb_esp == 0)
return 0;
read_memory (pcb->pcb_esp + 4, (gdb_byte *)&sf, sizeof sf);
regcache_raw_supply (regcache, I386_EDI_REGNUM, &sf.sf_edi);
regcache_raw_supply (regcache, I386_ESI_REGNUM, &sf.sf_esi);
regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp);
regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp);
regcache_raw_supply (regcache, I386_EBX_REGNUM, &sf.sf_ebx);
regcache_raw_supply (regcache, I386_EIP_REGNUM, &sf.sf_eip);
read_memory (pcb->pcb_esp, (gdb_byte *) &sf, sizeof sf);
if ( (unsigned long)sf.sf_eip >= (unsigned long)0xc0100000 )
{
/* Yes, we have a frame that matches cpu_switch(). */
pcb->pcb_esp += sizeof (struct switchframe);
regcache_raw_supply (regcache, I386_EDI_REGNUM, &sf.sf_edi);
regcache_raw_supply (regcache, I386_ESI_REGNUM, &sf.sf_esi);
regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp);
regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp);
regcache_raw_supply (regcache, I386_EBX_REGNUM, &sf.sf_ebx);
regcache_raw_supply (regcache, I386_EIP_REGNUM, &sf.sf_eip);
}
else
{
CORE_ADDR pc, fp;
/* No, the pcb must have been last updated by savectx() in
dumpsys. Use the frame pointer to recover enough state. */
read_memory (pcb->pcb_ebp, (gdb_byte *) &fp, sizeof(fp));
read_memory (pcb->pcb_ebp + 4, (gdb_byte *) &pc, sizeof(pc));
regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_ebp);
regcache_raw_supply (regcache, I386_EBP_REGNUM, &fp);
regcache_raw_supply (regcache, I386_EIP_REGNUM, &pc);
}
return 1;
}