1 /* Bounded-pointer definitions for x86 assembler.
2    Copyright (C) 2000 Free Software Foundation, Inc.
3    Contributed by Greg McGary <greg@mcgary.org>
4    This file is part of the GNU C Library.  Its master source is NOT part of
5    the C library, however.  The master source lives in the GNU MP Library.
6 
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11 
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16 
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, write to the Free
19    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20    02111-1307 USA.  */
21 
22 #ifndef _bp_asm_h_
23 # define _bp_asm_h_ 1
24 
25 # if __ASSEMBLER__
26 
27 #  if __BOUNDED_POINTERS__
28 
29 /* Bounded pointers occupy three words.  */
30 #   define PTR_SIZE 12
31 /* Bounded pointer return values are passed back through a hidden
32    argument that points to caller-allocate space.  The hidden arg
33    occupies one word on the stack.  */
34 #   define RTN_SIZE 4
35 /* Although the caller pushes the hidden arg, the callee is
36    responsible for popping it.  */
37 #   define RET_PTR ret $RTN_SIZE
38 /* Maintain frame pointer chain in leaf assembler functions for the benefit
39    of debugging stack traces when bounds violations occur.  */
40 #   define ENTER pushl %ebp; movl %esp, %ebp
41 #   define LEAVE movl %ebp, %esp; popl %ebp
42 /* Stack space overhead of procedure-call linkage: return address and
43    frame pointer.  */
44 #   define LINKAGE 8
45 /* Stack offset of return address after calling ENTER.  */
46 #   define PCOFF 4
47 
48 /* Int 5 is the "bound range" exception also raised by the "bound"
49    instruction.  */
50 #   define BOUNDS_VIOLATED int $5
51 
52 #   define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM)	\
53 	cmpl 4+BP_MEM, VAL_REG;			\
54 	jae 0f; /* continue if value >= low */	\
55 	BOUNDS_VIOLATED;			\
56     0:
57 
58 #   define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc)	\
59 	cmpl 8+BP_MEM, VAL_REG;				\
60 	Jcc 0f; /* continue if value < high */		\
61 	BOUNDS_VIOLATED;				\
62     0:
63 
64 #   define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM)	\
65 	cmpl 4+BP_MEM, VAL_REG;			\
66 	jb 1f; /* die if value < low */		\
67     	cmpl 8+BP_MEM, VAL_REG;			\
68 	jb 0f; /* continue if value < high */	\
69     1:	BOUNDS_VIOLATED;			\
70     0:
71 
72 #   define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH)	\
73 	CHECK_BOUNDS_LOW(VAL_REG, BP_MEM);			\
74 	addl LENGTH, VAL_REG;					\
75     	cmpl 8+BP_MEM, VAL_REG;					\
76 	jbe 0f; /* continue if value <= high */			\
77 	BOUNDS_VIOLATED;					\
78     0:	subl LENGTH, VAL_REG /* restore value */
79 
80 /* Take bounds from BP_MEM and affix them to the pointer
81    value in %eax, stuffing all into memory at RTN(%esp).
82    Use %edx as a scratch register.  */
83 
84 #   define RETURN_BOUNDED_POINTER(BP_MEM)	\
85 	movl RTN(%esp), %edx;			\
86 	movl %eax, 0(%edx);			\
87 	movl 4+BP_MEM, %eax;			\
88 	movl %eax, 4(%edx);			\
89 	movl 8+BP_MEM, %eax;			\
90 	movl %eax, 8(%edx)
91 
92 #   define RETURN_NULL_BOUNDED_POINTER		\
93 	movl RTN(%esp), %edx;			\
94 	movl %eax, 0(%edx);			\
95 	movl %eax, 4(%edx);			\
96 	movl %eax, 8(%edx)
97 
98 /* The caller of __errno_location is responsible for allocating space
99    for the three-word BP return-value and passing pushing its address
100    as an implicit first argument.  */
101 #   define PUSH_ERRNO_LOCATION_RETURN		\
102 	subl $8, %esp;				\
103 	subl $4, %esp;				\
104 	pushl %esp
105 
106 /* __errno_location is responsible for popping the implicit first
107    argument, but we must pop the space for the BP itself.  We also
108    dereference the return value in order to dig out the pointer value.  */
109 #   define POP_ERRNO_LOCATION_RETURN		\
110 	popl %eax;				\
111 	addl $8, %esp
112 
113 #  else /* !__BOUNDED_POINTERS__ */
114 
115 /* Unbounded pointers occupy one word.  */
116 #   define PTR_SIZE 4
117 /* Unbounded pointer return values are passed back in the register %eax.  */
118 #   define RTN_SIZE 0
119 /* Use simple return instruction for unbounded pointer values.  */
120 #   define RET_PTR ret
121 /* Don't maintain frame pointer chain for leaf assembler functions.  */
122 #   define ENTER
123 #   define LEAVE
124 /* Stack space overhead of procedure-call linkage: return address only.  */
125 #   define LINKAGE 4
126 /* Stack offset of return address after calling ENTER.  */
127 #   define PCOFF 0
128 
129 #   define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM)
130 #   define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc)
131 #   define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM)
132 #   define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH)
133 #   define RETURN_BOUNDED_POINTER(BP_MEM)
134 
135 #   define RETURN_NULL_BOUNDED_POINTER
136 
137 #   define PUSH_ERRNO_LOCATION_RETURN
138 #   define POP_ERRNO_LOCATION_RETURN
139 
140 #  endif /* !__BOUNDED_POINTERS__ */
141 
142 # endif /* __ASSEMBLER__ */
143 
144 #endif /* _bp_asm_h_ */
145