Skip to content
Snippets Groups Projects
Commit 72f0aa1e authored by toy's avatar toy
Browse files

Add control-stack checking for Sparc. Based on work from SBCL.

	* lisp/sunos-os.h (PROTECTION_VIOLATION_SIGNAL): Define it for
	stack-checking.

	* lisp/solaris-os.c (segv_handler): Add stack-checking support for
	Solaris.

	* lisp/os.h (os_control_stack_overflow): Give a type name to the
	zone enums (mostly for the debugger).

	* lisp/os-common.c (guard_zones): Add stack-checking support for
	Solaris.
	(os_control_stack_overflow): Add stack-checking support for
	Solaris.

	* lisp/interrupt.c (build_fake_control_stack_frame): New function
	for building a stack frame without the foreign call stuff.  Used
	for stack checking.
	(interrupt_install_low_level_handler): Only need to install
	alternate signal stack for x86.

	* lispinit.lisp:
	(scrub-control-stack): Rename to %scrub-control-stack to match x86
	version so control stack guard is done.

	* parms.lisp (static-symbols): Added new static symbols for
	control stack checking.
parent d8136b51
No related branches found
No related tags found
No related merge requests found
......@@ -5,7 +5,7 @@
;;; Carnegie Mellon University, and has been placed in the public domain.
;;;
(ext:file-comment
"$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/code/lispinit.lisp,v 1.68 2003/03/23 21:23:42 gerd Exp $")
"$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/code/lispinit.lisp,v 1.69 2003/05/29 22:03:01 toy Exp $")
;;;
;;; **********************************************************************
;;;
......@@ -506,7 +506,7 @@
;;; Scrub-control-stack.
;;;
#-x86
(defun scrub-control-stack ()
(defun %scrub-control-stack ()
"Zero the unused portion of the control stack so that old objects are not
kept alive because of uninitialized stack variables."
(declare (optimize (speed 3) (safety 0))
......@@ -545,7 +545,6 @@
;;; On the x86 port the stack grows downwards, and to support grow on
;;; demand stacks the stack must be decreased as it is scrubbed.
;;;
#+x86
(defun scrub-control-stack ()
"Zero the unused portion of the control stack so that old objects are not
kept alive because of uninitialized stack variables."
......
......@@ -5,7 +5,7 @@
;;; Carnegie Mellon University, and has been placed in the public domain.
;;;
(ext:file-comment
"$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/compiler/sparc/parms.lisp,v 1.40 2003/04/30 16:16:50 toy Exp $")
"$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/compiler/sparc/parms.lisp,v 1.41 2003/05/29 22:03:01 toy Exp $")
;;;
;;; **********************************************************************
;;;
......@@ -261,6 +261,8 @@
lisp::%initial-function
lisp::maybe-gc
kernel::internal-error
#+stack-checking kernel::yellow-zone-hit
#+stack-checking kernel::red-zone-hit
di::handle-breakpoint
lisp::fdefinition-object
......@@ -286,7 +288,10 @@
;;
lisp::*cmucl-lib*
lisp::*cmucl-core-path*
;;
;; Some spare static symbols. Useful for adding another static
;; symbol without having to do a cross-compile. Just rename one
;; of these to the desired name.
spare-9
spare-8
spare-7
......
/* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/interrupt.c,v 1.27 2003/03/23 21:23:41 gerd Exp $ */
/* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/interrupt.c,v 1.28 2003/05/29 22:03:01 toy Exp $ */
/* Interrupt handing magic. */
......@@ -56,6 +56,49 @@ static boolean maybe_gc_pending = FALSE;
* Utility routines used by various signal handlers. *
\****************************************************************/
void
build_fake_control_stack_frame(struct sigcontext *context)
{
#ifndef i386
lispobj oldcont;
/* Build a fake stack frame */
current_control_frame_pointer = (lispobj *)SC_REG(context, reg_CSP);
if ((lispobj *)SC_REG(context, reg_CFP)==current_control_frame_pointer) {
/* There is a small window during call where the callee's frame */
/* isn't built yet. */
if (LowtagOf(SC_REG(context, reg_CODE)) == type_FunctionPointer) {
/* We have called, but not built the new frame, so
build it for them. */
current_control_frame_pointer[0] = SC_REG(context, reg_OCFP);
current_control_frame_pointer[1] = SC_REG(context, reg_LRA);
current_control_frame_pointer += 8;
/* Build our frame on top of it. */
oldcont = (lispobj)SC_REG(context, reg_CFP);
}
else {
/* We haven't yet called, build our frame as if the
partial frame wasn't there. */
oldcont = (lispobj)SC_REG(context, reg_OCFP);
}
}
/* ### We can't tell if we are still in the caller if it had to
reg_ALLOCate the stack frame due to stack arguments. */
/* ### Can anything strange happen during return? */
else {
/* Normal case. */
oldcont = (lispobj)SC_REG(context, reg_CFP);
}
current_control_stack_pointer = current_control_frame_pointer + 8;
current_control_frame_pointer[0] = oldcont;
current_control_frame_pointer[1] = NIL;
current_control_frame_pointer[2] = (lispobj)SC_REG(context, reg_CODE);
#endif
}
void
fake_foreign_function_call(struct sigcontext *context)
{
......@@ -78,7 +121,7 @@ fake_foreign_function_call(struct sigcontext *context)
current_binding_stack_pointer = (lispobj *)SC_REG(context, reg_BSP);
#endif
#ifndef i386
#if !defined(i386) && 0
/* Build a fake stack frame */
current_control_frame_pointer = (lispobj *)SC_REG(context, reg_CSP);
if ((lispobj *)SC_REG(context, reg_CFP)==current_control_frame_pointer) {
......@@ -111,7 +154,10 @@ fake_foreign_function_call(struct sigcontext *context)
current_control_frame_pointer[0] = oldcont;
current_control_frame_pointer[1] = NIL;
current_control_frame_pointer[2] = (lispobj)SC_REG(context, reg_CODE);
#else
build_fake_control_stack_frame(context);
#endif
/* Do dynamic binding of the active interrupt context index
and save the context in the context array. */
......@@ -516,7 +562,10 @@ interrupt_install_low_level_handler (int signal, void handler (HANDLER_ARGS))
because, when we get that signal because of hitting a control
stack guard zone, it's not a good idea to use more of the
control stack for handling the signal. */
#ifdef RED_ZONE_HIT
/* But we only need this on x86 since the Lisp control stack and the
C control stack are the same. For others, they're separate so
the C stack can still be used. */
#if defined(RED_ZONE_HIT) && defined(x86)
if (signal == PROTECTION_VIOLATION_SIGNAL)
{
stack_t sigstack;
......
/*
$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/os-common.c,v 1.9 2003/03/23 21:23:41 gerd Exp $
$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/os-common.c,v 1.10 2003/05/29 22:03:01 toy Exp $
This code was written as part of the CMU Common Lisp project at
Carnegie Mellon University, and has been placed in the public domain.
......@@ -14,6 +14,8 @@
#include "internals.h"
#include "validate.h"
#include "lisp.h"
#include "lispregs.h"
#include "globals.h"
/* Except for os_zero, these routines are only called by Lisp code. These
routines may also be replaced by os-dependent versions instead. See
......@@ -291,7 +293,7 @@ os_stack_grows_down (void)
+----------+
| | yellow zone
+----------+
| | red zove
| | red zone
+----------+ CONTROL_STACK_START
Both the yellow zone and the red zone are write-protected.
......@@ -317,6 +319,7 @@ os_stack_grows_down (void)
static void
guard_zones (char **yellow_start, char **red_start)
{
#ifdef x86
if (os_stack_grows_down ())
{
char *end = (char *) CONTROL_STACK_START;
......@@ -329,6 +332,17 @@ guard_zones (char **yellow_start, char **red_start)
*red_start = end - RED_ZONE_SIZE;
*yellow_start = *red_start - YELLOW_ZONE_SIZE;
}
#else
/*
* On Solaris/sparc, the C stack grows down, but the Lisp control
* stack grows up. The stack zones begin just before the end of the
* control stack area.
*/
char *end = (char *) CONTROL_STACK_START + CONTROL_STACK_SIZE;
*red_start = end - RED_ZONE_SIZE;
*yellow_start = *red_start - YELLOW_ZONE_SIZE;
#endif
}
/* Return the guard zone FAULT_ADDR is in or 0 if not in a guard
......@@ -383,19 +397,24 @@ os_guard_control_stack (int zone, int guard)
int
os_control_stack_overflow (void *fault_addr, struct sigcontext *context)
{
int zone;
enum stack_zone_t zone;
zone = control_stack_zone (fault_addr);
if (zone == YELLOW_ZONE || zone == RED_ZONE)
{
lispobj error;
#if 0
fprintf(stderr, "hit end of control stack in zone %s\n",
(zone == YELLOW_ZONE) ? "YELLOW" : (zone == RED_ZONE) ? "RED" : "BOTH");
#endif
/* Unprotect the stack, giving us some room on the stack for
error handling in Lisp. Fake a stack frame for this
interruption. */
os_guard_control_stack (zone, 0);
fake_foreign_function_call (context);
build_fake_control_stack_frame (context);
/* The protection violation signal is delivered on a signal
stack different from the normal stack, so that we don't
......@@ -414,9 +433,19 @@ os_control_stack_overflow (void *fault_addr, struct sigcontext *context)
context->sc_eip = (int) ((struct function *) PTR (error))->code;
context->sc_ecx = 0;
#else
#ifdef sparc
/* This part should be common to all non-x86 ports */
SC_PC(context) = (long) ((struct function *) PTR (error))->code;
SC_NPC(context) = SC_PC(context) + 4;
SC_REG(context, reg_NARGS) = 0;
SC_REG(context, reg_LIP) = (long) ((struct function *) PTR (error))->code;
SC_REG(context, reg_CFP) = (long) current_control_frame_pointer;
/* This is sparc specific */
SC_REG(context, reg_CODE) = ((long) PTR(error)) + type_FunctionPointer;
#else
#error os_control_stack_overflow not implemented for this system
#endif
#endif
return 1;
}
......
/*
* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/os.h,v 1.11 2003/03/23 21:23:41 gerd Exp $
* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/os.h,v 1.12 2003/05/29 22:03:01 toy Exp $
*
* Common interface for os-dependent functions.
*
......@@ -105,7 +105,7 @@ extern boolean valid_addr(os_vm_address_t test);
extern void os_foreign_linkage_init(void);
extern void *os_dlsym (const char *sym_name, lispobj lib_list);
enum {BOTH_ZONES, YELLOW_ZONE, RED_ZONE};
enum stack_zone_t {BOTH_ZONES, YELLOW_ZONE, RED_ZONE};
extern int os_stack_grows_down (void);
extern void os_guard_control_stack (int zone, int guard);
extern int os_control_stack_overflow (void *, struct sigcontext *);
......
/*
* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/solaris-os.c,v 1.6 2002/11/13 13:10:22 toy Exp $
* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/solaris-os.c,v 1.7 2003/05/29 22:03:01 toy Exp $
*
* OS-dependent routines. This file (along with os.h) exports an
* OS-independent interface to the operating system VM facilities.
......@@ -203,8 +203,13 @@ segv_handler(HANDLER_ARGS)
caddr_t addr = code->si_addr;
SAVE_CONTEXT();
if(!interrupt_maybe_gc(signal, code, context)) {
#ifdef RED_ZONE_HIT
if (os_control_stack_overflow (addr, context))
return;
#endif
if (!interrupt_maybe_gc(signal, code, context)) {
/* a *real* protection fault */
fprintf(stderr, "segv_handler: Real protection violation: 0x%08x\n",
addr);
......
/*
$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/sunos-os.h,v 1.3 1994/10/27 17:13:54 ram Exp $
$Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/sunos-os.h,v 1.4 2003/05/29 22:03:01 toy Exp $
This code was written as part of the CMU Common Lisp project at
Carnegie Mellon University, and has been placed in the public domain.
......@@ -55,3 +55,5 @@ typedef int os_vm_prot_t;
#define bcopy(a,b,n) memmove(b,a,n)
#define bzero(a,n) memset(a,0,n)
#endif /* SOLARIS */
#define PROTECTION_VIOLATION_SIGNAL SIGSEGV
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment