Subject: port-pc532/11562: Gdb corrupts stack when executing code in inferior process
To: None <gnats-bugs@gnats.netbsd.org>
From: Ian Dall <ian@beware.dropbear.id.au>
List: netbsd-bugs
Date: 11/24/2000 16:12:14
>Number: 11562
>Category: port-pc532
>Synopsis: Gdb corrupts stack when executing code in inferior process
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: port-pc532-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Nov 24 16:12:00 PST 2000
>Closed-Date:
>Last-Modified:
>Originator: Ian Dall
>Release: <NetBSD-current source date> NetBSD-current 10 Nov 2000
>Organization:
>Environment:
System: NetBSD gateway.beware.dropbear.id.au 1.5_ALPHA NetBSD 1.5_ALPHA (SIBYL) #0: Sun Aug 13 15:28:38 CST 2000 ian@sibyl.beware.dropbear.id.au:/usr3/netbsd-src/bsrc/sys/arch/pc532/compile/SIBYL pc532
>Description:
Gdb corrupts stack when executing code in inferior process. The error message:
Error accessing memory address 0x0: Invalid argument.
warning: Unable to restore previously selected frame.
is produced.
>How-To-Repeat:
Debug pretty much any process containing a call to printf.
(gdb) break main
(gdb) run
(gdb) set printf ("Hello World")
>Fix:
diff -rc ../../../../src/gnu/dist/gdb/config/ns32k/tm-umax.h ./config/ns32k/tm-umax.h
*** ../../../../src/gnu/dist/gdb/config/ns32k/tm-umax.h Thu Sep 25 20:43:43 1997
--- ./config/ns32k/tm-umax.h Sun Jan 9 22:28:16 2000
***************
*** 19,24 ****
--- 19,30 ----
/* This is also included by tm-ns32km3.h, as well as being used by umax. */
+ #ifdef __STDC__ /* Forward decl's for prototypes */
+ struct frame_info;
+ struct frame_saved_regs;
+ struct type;
+ #endif
+
#define TARGET_BYTE_ORDER LITTLE_ENDIAN
/* Need to get function ends by adding this to epilogue address from .bf
***************
*** 281,349 ****
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
! #define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
! { \
! register int regmask, regnum; \
! int localcount; \
! register CORE_ADDR enter_addr; \
! register CORE_ADDR next_addr; \
! \
! memset (&(frame_saved_regs), '\0', sizeof (frame_saved_regs)); \
! enter_addr = ns32k_get_enter_addr ((frame_info)->pc); \
! if (enter_addr > 1) \
! { \
! regmask = read_memory_integer (enter_addr+1, 1) & 0xff; \
! localcount = ns32k_localcount (enter_addr); \
! next_addr = (frame_info)->frame + localcount; \
! for (regnum = 0; regnum < 8; regnum++, regmask >>= 1) \
! (frame_saved_regs).regs[regnum] = (regmask & 1) ? \
! (next_addr -= 4) : 0; \
! (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 4;\
! (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4;\
! (frame_saved_regs).regs[FP_REGNUM] = \
! (read_memory_integer ((frame_info)->frame, 4));\
! } \
! else if (enter_addr == 1) \
! { \
! CORE_ADDR sp = read_register (SP_REGNUM); \
! (frame_saved_regs).regs[PC_REGNUM] = sp; \
! (frame_saved_regs).regs[SP_REGNUM] = sp + 4; \
! } \
! }
/* Things needed for making the inferior call functions. */
/* Push an empty stack frame, to record the current PC, etc. */
! #define PUSH_DUMMY_FRAME \
! { register CORE_ADDR sp = read_register (SP_REGNUM);\
! register int regnum; \
! sp = push_word (sp, read_register (PC_REGNUM)); \
! sp = push_word (sp, read_register (FP_REGNUM)); \
! write_register (FP_REGNUM, sp); \
! for (regnum = 0; regnum < 8; regnum++) \
! sp = push_word (sp, read_register (regnum)); \
! write_register (SP_REGNUM, sp); \
! }
/* Discard from the stack the innermost frame, restoring all registers. */
! #define POP_FRAME \
! { register struct frame_info *frame = get_current_frame (); \
! register CORE_ADDR fp; \
! register int regnum; \
! struct frame_saved_regs fsr; \
! struct frame_info *fi; \
! fp = frame->frame; \
! get_frame_saved_regs (frame, &fsr); \
! for (regnum = 0; regnum < 8; regnum++) \
! if (fsr.regs[regnum]) \
! write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
! write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
! write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
! write_register (SP_REGNUM, fp + 8); \
! flush_cached_frames (); \
! }
/* This sequence of words is the instructions
enter 0xff,0 82 ff 00
--- 287,315 ----
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
! #define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
! { ns32k_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
!
! extern void ns32k_frame_find_saved_regs PARAMS ((struct frame_info *,
! struct frame_saved_regs *));
/* Things needed for making the inferior call functions. */
/* Push an empty stack frame, to record the current PC, etc. */
! /* Push an empty stack frame, to record the current PC, etc. */
!
! #define PUSH_DUMMY_FRAME { ns32k_push_dummy_frame (); }
!
! extern void ns32k_push_dummy_frame PARAMS ((void));
!
/* Discard from the stack the innermost frame, restoring all registers. */
! #define POP_FRAME { ns32k_pop_frame (); }
!
! extern void ns32k_pop_frame PARAMS ((void));
!
/* This sequence of words is the instructions
enter 0xff,0 82 ff 00
diff -rc ../../../../src/gnu/dist/gdb/ns32k-tdep.c ./ns32k-tdep.c
*** ../../../../src/gnu/dist/gdb/ns32k-tdep.c Tue Mar 2 22:37:44 1999
--- ./ns32k-tdep.c Sun Jan 9 22:28:14 2000
***************
*** 19,24 ****
--- 19,25 ----
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
+ #include "inferior.h"
void
_initialize_ns32k_tdep ()
***************
*** 156,159 ****
--- 157,256 ----
return 0; /* function has no enter/exit */
return enter_addr; /* pc is between enter and exit */
+ }
+
+ void ns32k_frame_find_saved_regs (frame_info, frame_saved_regs)
+ struct frame_info *frame_info;
+ struct frame_saved_regs *frame_saved_regs;
+ {
+ int regmask, regnum;
+ int localcount;
+ CORE_ADDR enter_addr;
+ CORE_ADDR next_addr;
+ CORE_ADDR dummy_bottom;
+
+ memset (frame_saved_regs, '\0', sizeof *frame_saved_regs);
+ /* if frame is the end of a dummy, compute where the
+ * beginning would be
+ */
+ dummy_bottom = (frame_info->frame - 4 - REGISTER_BYTES - CALL_DUMMY_LENGTH);
+
+ /* check if the PC is in the stack, in a dummy frame */
+ if (dummy_bottom <= frame_info->pc && frame_info->pc <= frame_info->frame)
+ {
+ /* all regs were saved by PUSH_DUMMY_FRAME */
+ CORE_ADDR adr = frame_info->frame;
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ {
+ adr -= REGISTER_RAW_SIZE (regnum);
+ frame_saved_regs->regs[regnum] = adr;
+ }
+ return;
+ }
+
+ enter_addr = ns32k_get_enter_addr (frame_info->pc);
+ if (enter_addr > 1)
+ {
+ regmask = read_memory_integer (enter_addr+1, 1) & 0xff;
+ localcount = ns32k_localcount (enter_addr);
+ next_addr = frame_info->frame + localcount;
+ for (regnum = 0; regnum < 8; regnum++, regmask >>= 1)
+ frame_saved_regs->regs[regnum] = (regmask & 1) ?
+ (next_addr -= 4) : 0;
+ frame_saved_regs->regs[SP_REGNUM] = frame_info->frame + 4;
+ frame_saved_regs->regs[PC_REGNUM] = frame_info->frame + 4;
+ frame_saved_regs->regs[FP_REGNUM] =
+ (read_memory_integer (frame_info->frame, 4));
+ }
+ else if (enter_addr == 1)
+ {
+ CORE_ADDR sp = read_register (SP_REGNUM);
+ frame_saved_regs->regs[PC_REGNUM] = sp;
+ frame_saved_regs->regs[SP_REGNUM] = sp + 4;
+ }
+ }
+
+ void ns32k_push_dummy_frame()
+ {
+ register CORE_ADDR sp = read_register (SP_REGNUM);
+ register int regnum;
+ char regbuf[MAX_REGISTER_RAW_SIZE];
+
+ sp = push_word (sp, read_register (PC_REGNUM));
+ sp = push_word (sp, read_register (FP_REGNUM));
+ write_register (FP_REGNUM, sp);
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ {
+ read_register_gen (regnum, regbuf);
+ sp = push_bytes (sp, regbuf, REGISTER_RAW_SIZE (regnum));
+ }
+ write_register (SP_REGNUM, sp);
+ }
+
+
+ void ns32k_pop_frame ()
+ {
+ struct frame_info *frame = get_current_frame ();
+ CORE_ADDR fp;
+ int regnum;
+ struct frame_saved_regs fsr;
+ char regbuf[MAX_REGISTER_RAW_SIZE];
+
+ struct frame_info *fi;
+ fp = frame->frame;
+ get_frame_saved_regs (frame, &fsr);
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ {
+ CORE_ADDR adr = fsr.regs[regnum];
+ if (adr)
+ {
+ read_memory (adr, regbuf, REGISTER_RAW_SIZE (regnum));
+ write_register_bytes (REGISTER_BYTE (regnum), regbuf,
+ REGISTER_RAW_SIZE (regnum));
+ }
+ }
+ write_register (FP_REGNUM, read_memory_integer (fp, 4));
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
+ write_register (SP_REGNUM, fp + 8);
+ flush_cached_frames ();
}
>Release-Note:
>Audit-Trail:
>Unformatted: