145 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C
		
	
	
	
| /* Bounded-pointer definitions for x86 assembler.
 | |
|    Copyright (C) 2000 Free Software Foundation, Inc.
 | |
|    Contributed by Greg McGary <greg@mcgary.org>
 | |
|    This file is part of the GNU C Library.  Its master source is NOT part of
 | |
|    the C library, however.  The master source lives in the GNU MP Library.
 | |
| 
 | |
|    The GNU C Library is free software; you can redistribute it and/or
 | |
|    modify it under the terms of the GNU Lesser General Public
 | |
|    License as published by the Free Software Foundation; either
 | |
|    version 2.1 of the License, or (at your option) any later version.
 | |
| 
 | |
|    The GNU C Library is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|    Lesser General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU Lesser General Public
 | |
|    License along with the GNU C Library; if not, write to the Free
 | |
|    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 | |
|    02111-1307 USA.  */
 | |
| 
 | |
| #ifndef _bp_asm_h_
 | |
| # define _bp_asm_h_ 1
 | |
| 
 | |
| # if __ASSEMBLER__
 | |
| 
 | |
| #  if __BOUNDED_POINTERS__
 | |
| 
 | |
| /* Bounded pointers occupy three words.  */
 | |
| #   define PTR_SIZE 12
 | |
| /* Bounded pointer return values are passed back through a hidden
 | |
|    argument that points to caller-allocate space.  The hidden arg
 | |
|    occupies one word on the stack.  */
 | |
| #   define RTN_SIZE 4
 | |
| /* Although the caller pushes the hidden arg, the callee is
 | |
|    responsible for popping it.  */
 | |
| #   define RET_PTR ret $RTN_SIZE
 | |
| /* Maintain frame pointer chain in leaf assembler functions for the benefit
 | |
|    of debugging stack traces when bounds violations occur.  */
 | |
| #   define ENTER pushl %ebp; movl %esp, %ebp
 | |
| #   define LEAVE movl %ebp, %esp; popl %ebp
 | |
| /* Stack space overhead of procedure-call linkage: return address and
 | |
|    frame pointer.  */
 | |
| #   define LINKAGE 8
 | |
| /* Stack offset of return address after calling ENTER.  */
 | |
| #   define PCOFF 4
 | |
| 
 | |
| /* Int 5 is the "bound range" exception also raised by the "bound"
 | |
|    instruction.  */
 | |
| #   define BOUNDS_VIOLATED int $5
 | |
| 
 | |
| #   define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM)	\
 | |
| 	cmpl 4+BP_MEM, VAL_REG;			\
 | |
| 	jae 0f; /* continue if value >= low */	\
 | |
| 	BOUNDS_VIOLATED;			\
 | |
|     0:
 | |
| 
 | |
| #   define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc)	\
 | |
| 	cmpl 8+BP_MEM, VAL_REG;				\
 | |
| 	Jcc 0f; /* continue if value < high */		\
 | |
| 	BOUNDS_VIOLATED;				\
 | |
|     0:
 | |
| 
 | |
| #   define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM)	\
 | |
| 	cmpl 4+BP_MEM, VAL_REG;			\
 | |
| 	jb 1f; /* die if value < low */		\
 | |
|     	cmpl 8+BP_MEM, VAL_REG;			\
 | |
| 	jb 0f; /* continue if value < high */	\
 | |
|     1:	BOUNDS_VIOLATED;			\
 | |
|     0:
 | |
| 
 | |
| #   define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH)	\
 | |
| 	CHECK_BOUNDS_LOW(VAL_REG, BP_MEM);			\
 | |
| 	addl LENGTH, VAL_REG;					\
 | |
|     	cmpl 8+BP_MEM, VAL_REG;					\
 | |
| 	jbe 0f; /* continue if value <= high */			\
 | |
| 	BOUNDS_VIOLATED;					\
 | |
|     0:	subl LENGTH, VAL_REG /* restore value */
 | |
| 
 | |
| /* Take bounds from BP_MEM and affix them to the pointer
 | |
|    value in %eax, stuffing all into memory at RTN(%esp).
 | |
|    Use %edx as a scratch register.  */
 | |
| 
 | |
| #   define RETURN_BOUNDED_POINTER(BP_MEM)	\
 | |
| 	movl RTN(%esp), %edx;			\
 | |
| 	movl %eax, 0(%edx);			\
 | |
| 	movl 4+BP_MEM, %eax;			\
 | |
| 	movl %eax, 4(%edx);			\
 | |
| 	movl 8+BP_MEM, %eax;			\
 | |
| 	movl %eax, 8(%edx)
 | |
| 
 | |
| #   define RETURN_NULL_BOUNDED_POINTER		\
 | |
| 	movl RTN(%esp), %edx;			\
 | |
| 	movl %eax, 0(%edx);			\
 | |
| 	movl %eax, 4(%edx);			\
 | |
| 	movl %eax, 8(%edx)
 | |
| 
 | |
| /* The caller of __errno_location is responsible for allocating space
 | |
|    for the three-word BP return-value and passing pushing its address
 | |
|    as an implicit first argument.  */
 | |
| #   define PUSH_ERRNO_LOCATION_RETURN		\
 | |
| 	subl $8, %esp;				\
 | |
| 	subl $4, %esp;				\
 | |
| 	pushl %esp
 | |
| 
 | |
| /* __errno_location is responsible for popping the implicit first
 | |
|    argument, but we must pop the space for the BP itself.  We also
 | |
|    dereference the return value in order to dig out the pointer value.  */
 | |
| #   define POP_ERRNO_LOCATION_RETURN		\
 | |
| 	popl %eax;				\
 | |
| 	addl $8, %esp
 | |
| 
 | |
| #  else /* !__BOUNDED_POINTERS__ */
 | |
| 
 | |
| /* Unbounded pointers occupy one word.  */
 | |
| #   define PTR_SIZE 4
 | |
| /* Unbounded pointer return values are passed back in the register %eax.  */
 | |
| #   define RTN_SIZE 0
 | |
| /* Use simple return instruction for unbounded pointer values.  */
 | |
| #   define RET_PTR ret
 | |
| /* Don't maintain frame pointer chain for leaf assembler functions.  */
 | |
| #   define ENTER
 | |
| #   define LEAVE
 | |
| /* Stack space overhead of procedure-call linkage: return address only.  */
 | |
| #   define LINKAGE 4
 | |
| /* Stack offset of return address after calling ENTER.  */
 | |
| #   define PCOFF 0
 | |
| 
 | |
| #   define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM)
 | |
| #   define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc)
 | |
| #   define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM)
 | |
| #   define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH)
 | |
| #   define RETURN_BOUNDED_POINTER(BP_MEM)
 | |
| 
 | |
| #   define RETURN_NULL_BOUNDED_POINTER
 | |
| 
 | |
| #   define PUSH_ERRNO_LOCATION_RETURN
 | |
| #   define POP_ERRNO_LOCATION_RETURN
 | |
| 
 | |
| #  endif /* !__BOUNDED_POINTERS__ */
 | |
| 
 | |
| # endif /* __ASSEMBLER__ */
 | |
| 
 | |
| #endif /* _bp_asm_h_ */
 |