Remove assert in get_def_bb_for_const
[official-gcc.git] / libmpx / mpxwrap / mpx_wrappers.c
blobd4c83ef484cac63e4800181c05c75cf22b9377d8
1 /* MPX Wrappers Library
2 Copyright (C) 2014 Free Software Foundation, Inc.
3 Contributed by Ilya Enkovich (ilya.enkovich@intel.com)
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "stdlib.h"
27 #include "string.h"
28 #include <sys/mman.h>
29 #include <stdint.h>
30 #include "mpxrt/mpxrt.h"
32 void *
33 __mpx_wrapper_malloc (size_t size)
35 void *p = (void *)malloc (size);
36 if (!p) return __bnd_null_ptr_bounds (p);
37 return __bnd_set_ptr_bounds (p, size);
41 void *
42 __mpx_wrapper_mmap (void *addr, size_t length, int prot, int flags,
43 int fd, off_t offset)
45 void *p = mmap (addr, length, prot, flags, fd, offset);
46 if (!p) return __bnd_null_ptr_bounds (p);
47 return __bnd_set_ptr_bounds (p, length);
50 void *
51 __mpx_wrapper_realloc (void *ptr, size_t n)
53 if (!ptr)
54 return __mpx_wrapper_malloc (n);
56 /* We don't kwnow how much data is copied by realloc
57 and therefore may check only lower bounds. */
58 __bnd_chk_ptr_lbounds (ptr);
59 ptr = realloc (ptr, n);
61 if (!ptr)
62 return __bnd_null_ptr_bounds (ptr);
64 return __bnd_set_ptr_bounds (ptr, n);
67 void *
68 __mpx_wrapper_calloc (size_t n_elements, size_t element_size)
70 void *p = calloc (n_elements, element_size);
71 if (!p)
72 return __bnd_null_ptr_bounds (p);
73 return __bnd_set_ptr_bounds (p, n_elements * element_size);
76 void *
77 __mpx_wrapper_memset (void *dstpp, int c, size_t len)
79 if (len > 0)
81 __bnd_chk_ptr_bounds (dstpp, len);
82 memset (dstpp, c, len);
84 return dstpp;
87 void
88 __mpx_wrapper_bzero (void *dst, size_t len)
90 __mpx_wrapper_memset (dst, 0, len);
93 /* The mpx_pointer type is used for getting bits
94 for bt_index (index in bounds table) and
95 bd_index (index in bounds directory). */
96 typedef union
98 struct
100 unsigned long ignored:NUM_IGN_BITS;
101 unsigned long l2entry:NUM_L2_BITS;
102 unsigned long l1index:NUM_L1_BITS;
104 void *pointer;
105 } mpx_pointer;
107 /* The mpx_bt_entry struct represents a cell in bounds table.
108 lb is the lower bound, ub is the upper bound,
109 p is the stored pointer. */
110 struct mpx_bt_entry
112 void *lb;
113 void *ub;
114 void *p;
115 void *reserved;
118 /* A special type for bd is needed because bt addresses can be modified. */
119 typedef struct mpx_bt_entry * volatile * bd_type;
121 /* Function alloc_bt is used for allocating bounds table
122 for the destination pointers if we don't have one.
123 We generate a bounds store for some pointer belonging
124 to that table and kernel allocates the table for us. */
125 static inline void __attribute__ ((bnd_legacy))
126 alloc_bt (void *ptr)
128 __asm__ __volatile__ ("bndstx %%bnd0, (%0,%0)"::"r" (ptr):"%bnd0");
131 /* get_bt returns address of bounds table that should
132 exist at BD[BD_INDEX]. If there is no address or the address is not valid,
133 we try to allocate a valid table.
134 If we succeed in getting bt, its address will be returned.
135 If we can't get a valid bt, NULL will be returned. */
136 __attribute__ ((bnd_legacy)) static inline struct mpx_bt_entry *
137 get_bt (unsigned bd_index, bd_type bd)
139 struct mpx_bt_entry *bt = (struct mpx_bt_entry *) ((uintptr_t) bd[bd_index]
140 & MPX_L2_ADDR_MASK);
141 if (!(bt) || !((uintptr_t) bd[bd_index] & MPX_L2_VALID_MASK))
143 mpx_pointer ptr;
144 ptr.l1index = bd_index;
145 /* If we don't have BT, allocate it. */
146 alloc_bt (ptr.pointer);
147 bt = (struct mpx_bt_entry *) ((uintptr_t) bd[bd_index]
148 & MPX_L2_ADDR_MASK);
149 if (!(bt) || !((uintptr_t) bd[bd_index] & MPX_L2_VALID_MASK))
150 return NULL;
152 return bt;
155 /* Function copy_if_possible moves elements from *FROM to *TO.
156 If ELEMS is less then the ELEMS_TO_COPY (elements we can copy),
157 it copies ELEMS elements and returns 0.
158 Otherwise, it copies ELEMS_TO_COPY elements and returns 1. */
159 __attribute__ ((bnd_legacy)) static inline int
160 copy_if_possible (int elems, int elems_to_copy, struct mpx_bt_entry *from,
161 struct mpx_bt_entry *to)
163 if (elems < elems_to_copy)
164 memmove (to, from, elems * sizeof (struct mpx_bt_entry));
165 else
167 memmove (to, from, elems_to_copy * sizeof (struct mpx_bt_entry));
168 return 1;
170 return 0;
173 /* Function copy_if_possible_from_end moves elements ending at *SRC_END
174 to the place where they will end at *DST_END.
175 If ELEMS is less then the ELEMS_TO_COPY (elements we can copy),
176 function copies ELEMS elements and returns 0.
177 Otherwise, it copies ELEMS_TO_COPY elements and returns 1. */
178 __attribute__ ((bnd_legacy)) static inline int
179 copy_if_possible_from_end (int elems, int elems_to_copy, struct mpx_bt_entry
180 *src_end, struct mpx_bt_entry *dst_end)
182 if (elems < elems_to_copy)
183 memmove (dst_end - elems, src_end - elems,
184 elems * sizeof (struct mpx_bt_entry));
185 else
187 memmove (dst_end - elems_to_copy,
188 src_end - elems_to_copy,
189 elems_to_copy * sizeof (struct mpx_bt_entry));
190 return 1;
192 return 0;
195 /* move_bounds function copies bounds for N bytes from bt of SRC to bt of DST.
196 It also copies bounds for all pointers inside.
197 There are 3 parts of the algorithm:
198 1) We copy everything till the end of the first bounds table of SRC
199 2) In loop we copy whole bound tables till the second-last one
200 3) Data in the last bounds table is copied separately, after the loop.
201 If one of bound tables in SRC doesn't exist,
202 we skip it because there are no pointers.
203 Depending on the arrangement of SRC and DST we copy from the beginning
204 or from the end. */
205 __attribute__ ((bnd_legacy)) static void
206 move_bounds (void *dst, const void *src, size_t n)
208 bd_type bd = (bd_type)get_bd ();
209 if (!(bd))
210 return;
212 /* We get indexes for all tables and number of elements for BT. */
213 unsigned long bt_num_of_elems = (1UL << NUM_L2_BITS);
214 mpx_pointer addr_src, addr_dst, addr_src_end, addr_dst_end;
215 addr_src.pointer = (char *) src;
216 addr_dst.pointer = (char *) dst;
217 addr_src_end.pointer = (char *) src + n - 1;
218 addr_dst_end.pointer = (char *) dst + n - 1;
219 unsigned dst_bd_index = addr_dst.l1index;
220 unsigned src_bd_index = addr_src.l1index;
221 unsigned dst_bt_index = addr_dst.l2entry;
222 unsigned src_bt_index = addr_src.l2entry;
224 unsigned dst_bd_index_end = addr_dst_end.l1index;
225 unsigned src_bd_index_end = addr_src_end.l1index;
226 unsigned dst_bt_index_end = addr_dst_end.l2entry;
227 unsigned src_bt_index_end = addr_src_end.l2entry;
229 int elems_to_copy = src_bt_index_end - src_bt_index + 1 + (src_bd_index_end
230 - src_bd_index) * bt_num_of_elems;
231 struct mpx_bt_entry *bt_src, *bt_dst;
232 uintptr_t bt_valid;
233 /* size1 and size2 will be used to find out what portions
234 can be used to copy data. */
235 int size1_elem, size2_elem, size1_bytes, size2_bytes;
237 /* Copy from the beginning. */
238 if (((char *) src - (char *) dst) > 0)
240 /* Copy everything till the end of the first bounds table (src) */
241 bt_src = (struct mpx_bt_entry *) ((uintptr_t) bd[src_bd_index]
242 & MPX_L2_ADDR_MASK);
243 bt_valid = (uintptr_t) bd[src_bd_index] & MPX_L2_VALID_MASK;
245 /* We can copy the whole preliminary piece of data. */
246 if (src_bt_index > dst_bt_index)
248 size1_elem = src_bt_index - dst_bt_index;
249 size2_elem = bt_num_of_elems - size1_elem;
250 size1_bytes = size1_elem * sizeof (struct mpx_bt_entry);
251 size2_bytes = size2_elem * sizeof (struct mpx_bt_entry);
253 /* Check we have bounds to copy. */
254 if (bt_src && bt_valid)
256 bt_dst = get_bt (dst_bd_index, bd);
257 if (!bt_dst)
258 return;
259 if (copy_if_possible (bt_num_of_elems - src_bt_index,
260 elems_to_copy, &(bt_src[src_bt_index]),
261 &(bt_dst[dst_bt_index])))
262 return;
264 elems_to_copy -= bt_num_of_elems - src_bt_index;
266 /* We have to copy preliminary data in two parts. */
267 else
269 size2_elem = dst_bt_index - src_bt_index;
270 size1_elem = bt_num_of_elems - size2_elem;
271 size1_bytes = size1_elem * sizeof (struct mpx_bt_entry);
272 size2_bytes = size2_elem * sizeof (struct mpx_bt_entry);
274 /* Check we have bounds to copy. */
275 if (bt_src && bt_valid)
277 bt_dst = get_bt (dst_bd_index, bd);
278 if (!bt_dst)
279 return;
281 if (copy_if_possible (bt_num_of_elems - dst_bt_index,
282 elems_to_copy, &(bt_src[src_bt_index]),
283 &(bt_dst[dst_bt_index])))
284 return;
285 elems_to_copy -= bt_num_of_elems - dst_bt_index;
287 dst_bd_index++;
289 bt_dst = get_bt (dst_bd_index, bd);
290 if (!bt_dst)
291 return;
292 if (copy_if_possible (size2_elem, elems_to_copy,
293 &(bt_src[size1_elem]), &(bt_dst[0])))
294 return;
295 elems_to_copy -= size2_elem;
297 else
298 elems_to_copy -= bt_num_of_elems - src_bt_index;
300 src_bd_index++;
302 /* For each bounds table check if it's valid and move it. */
303 for (; src_bd_index < src_bd_index_end; src_bd_index++)
305 bt_src = (struct mpx_bt_entry *) ((uintptr_t) bd[src_bd_index]
306 & MPX_L2_ADDR_MASK);
307 bt_valid = (uintptr_t) bd[src_bd_index] & MPX_L2_VALID_MASK;
309 /* Check we have bounds to copy. */
310 if (!bt_src || !bt_valid)
311 dst_bd_index++;
312 else
314 bt_dst = get_bt (dst_bd_index, bd);
315 if (!bt_dst)
316 return;
317 memmove (&(bt_dst[size2_elem]), &(bt_src[0]), size1_bytes);
318 dst_bd_index++;
319 bt_dst = get_bt (dst_bd_index, bd);
320 if (!bt_dst)
321 return;
322 memmove (&(bt_dst[0]), &(bt_src[size1_elem]), size2_bytes);
324 elems_to_copy -= bt_num_of_elems;
327 /* Now we have the last page that may be not full
328 we copy it separately. */
329 if (elems_to_copy > 0)
331 bt_src = (struct mpx_bt_entry *) ((uintptr_t) bd[src_bd_index]
332 & MPX_L2_ADDR_MASK);
333 bt_valid = (uintptr_t) bd[src_bd_index] & MPX_L2_VALID_MASK;
335 /* Check we have bounds to copy. */
336 if (bt_src && bt_valid)
338 bt_dst = get_bt (dst_bd_index, bd);
339 if (!bt_dst)
340 return;
342 if (copy_if_possible (size1_elem, elems_to_copy, &(bt_src[0]),
343 &(bt_dst[size2_elem])))
344 return;
346 elems_to_copy -= size1_elem;
347 dst_bd_index++;
348 bt_dst = get_bt (dst_bd_index, bd);
349 if (!bt_dst)
350 return;
351 memmove (&(bt_dst[0]), &(bt_src[size1_elem]),
352 elems_to_copy * sizeof (struct mpx_bt_entry));
357 /* Copy from the end. */
358 else
360 /* Copy everything till the end of the first bounds table (src) */
361 bt_src = (struct mpx_bt_entry *) ((uintptr_t) bd[src_bd_index_end]
362 & MPX_L2_ADDR_MASK);
363 bt_valid = (uintptr_t) bd[src_bd_index_end] & MPX_L2_VALID_MASK;
365 if (src_bt_index_end <= dst_bt_index_end)
366 /* We can copy the whole preliminary piece of data. */
368 size2_elem = dst_bt_index_end - src_bt_index_end;
369 size1_elem = bt_num_of_elems - size2_elem;
370 size1_bytes = size1_elem * sizeof (struct mpx_bt_entry);
371 size2_bytes = size2_elem * sizeof (struct mpx_bt_entry);
373 /* Check we have bounds to copy. */
374 if (bt_src && bt_valid)
376 bt_dst = get_bt (dst_bd_index_end, bd);
377 if (!bt_dst)
378 return;
380 if (copy_if_possible_from_end (src_bt_index_end + 1,
381 elems_to_copy, &(bt_src[src_bt_index_end + 1]),
382 &(bt_dst[dst_bt_index_end + 1])))
383 return;
385 elems_to_copy -= src_bt_index_end + 1;
387 /* We have to copy preliminary data in two parts. */
388 else
390 size1_elem = src_bt_index_end - dst_bt_index_end;
391 size2_elem = bt_num_of_elems - size1_elem;
392 size1_bytes = size1_elem * sizeof (struct mpx_bt_entry);
393 size2_bytes = size2_elem * sizeof (struct mpx_bt_entry);
395 /* Check we have bounds to copy. */
396 if (bt_src && bt_valid)
398 bt_dst = get_bt (dst_bd_index_end, bd);
399 if (!bt_dst)
400 return;
401 if (copy_if_possible_from_end (dst_bt_index_end + 1,
402 elems_to_copy, &(bt_src[src_bt_index_end + 1]),
403 &(bt_dst[dst_bt_index_end + 1])))
404 return;
405 elems_to_copy -= dst_bt_index_end + 1;
407 dst_bd_index_end--;
409 bt_dst = get_bt (dst_bd_index_end, bd);
410 if (!bt_dst)
411 return;
412 if (copy_if_possible_from_end (size1_elem, elems_to_copy,
413 &(bt_src[size1_elem]), &(bt_dst[bt_num_of_elems])))
414 return;
416 elems_to_copy -= size1_elem;
418 else
419 elems_to_copy -= src_bt_index_end + 1;
421 src_bd_index_end--;
422 /* For each bounds table we check if there are valid pointers inside.
423 If there are some, we copy table in pre-counted portions. */
424 for (; src_bd_index_end > src_bd_index; src_bd_index_end--)
426 bt_src = (struct mpx_bt_entry *) ((uintptr_t) bd[src_bd_index_end]
427 & MPX_L2_ADDR_MASK);
428 bt_valid = (uintptr_t) bd[src_bd_index_end] & MPX_L2_VALID_MASK;
429 /* Check we have bounds to copy. */
430 if (!bt_src || !bt_valid)
431 dst_bd_index_end--;
432 else
434 bt_dst = get_bt (dst_bd_index_end, bd);
435 if (!bt_dst)
436 return;
437 memmove (&(bt_dst[0]), &(bt_src[size1_elem]), size2_bytes);
438 dst_bd_index_end--;
439 bt_dst = get_bt (dst_bd_index_end, bd);
440 if (!bt_dst)
441 return;
442 memmove (&(bt_dst[size2_elem]), &(bt_src[0]), size1_bytes);
444 elems_to_copy -= bt_num_of_elems;
447 /* Now we have the last page that may be not full
448 we copy it separately. */
449 if (elems_to_copy > 0)
451 bt_src = (struct mpx_bt_entry *) ((uintptr_t) bd[src_bd_index_end]
452 & MPX_L2_ADDR_MASK);
453 bt_valid = (uintptr_t) bd[src_bd_index_end] & MPX_L2_VALID_MASK;
454 /* Check we have bounds to copy. */
455 if (bt_src && bt_valid)
457 bt_dst = get_bt (dst_bd_index_end, bd);
458 if (!bt_dst)
459 return;
460 if (copy_if_possible_from_end (size2_elem, elems_to_copy,
461 &(bt_src[bt_num_of_elems]), &(bt_dst[size2_elem])))
462 return;
464 elems_to_copy -= size2_elem;
465 dst_bd_index_end--;
466 bt_dst = get_bt (dst_bd_index_end, bd);
467 if (!bt_dst)
468 return;
469 memmove (&(bt_dst[dst_bt_index]), &(bt_src[src_bt_index]),
470 elems_to_copy * sizeof (struct mpx_bt_entry));
474 return;
477 void *
478 __mpx_wrapper_memmove (void *dst, const void *src, size_t n)
480 if (n == 0)
481 return dst;
483 __bnd_chk_ptr_bounds (dst, n);
484 __bnd_chk_ptr_bounds (src, n);
486 /* When we copy exactly one pointer it is faster to
487 just use bndldx + bndstx. */
488 if (n == sizeof (void *))
490 void *const *s = (void *const *) src;
491 void **d = (void **) dst;
492 *d = *s;
493 return dst;
496 memmove (dst, src, n);
498 /* Not necessary to copy bounds if size is less then size of pointer
499 or SRC==DST. */
500 if ((n >= sizeof (void *)) && (src != dst))
501 move_bounds (dst, src, n);
503 return dst;
507 void *
508 __mpx_wrapper_memcpy (void *dst, const void *src, size_t n)
510 return __mpx_wrapper_memmove (dst, src, n);
513 void *
514 __mpx_wrapper_mempcpy (void *dst, const void *src, size_t n)
516 return (char *)__mpx_wrapper_memcpy (dst, src, n) + n;
519 char *
520 __mpx_wrapper_strncat (char *dst, const char *src, size_t n)
522 size_t dst_size = strlen (dst);
523 size_t src_size = strnlen (src, n);
525 __bnd_chk_ptr_bounds (dst, dst_size + src_size + 1);
526 if (src_size < n)
527 __bnd_chk_ptr_bounds (src, src_size + 1);
528 else
529 __bnd_chk_ptr_bounds (src, src_size);
531 strncat (dst, src, n);
533 return dst;
536 char *
537 __mpx_wrapper_strcat (char *dst, const char *src)
539 size_t dst_size = strlen (dst);
540 size_t src_size = strlen (src);
542 __bnd_chk_ptr_bounds (dst, dst_size + src_size + 1);
543 __bnd_chk_ptr_bounds (src, src_size + 1);
545 strcat (dst, src);
547 return dst;
550 char *
551 __mpx_wrapper_stpcpy (char *dst, const char *src)
553 size_t src_size = strlen (src);
555 __bnd_chk_ptr_bounds (dst, src_size + 1);
556 __bnd_chk_ptr_bounds (src, src_size + 1);
558 memcpy (dst, src, src_size + 1);
560 return dst + src_size;
563 char *
564 __mpx_wrapper_stpncpy (char *dst, const char *src, size_t n)
566 size_t src_size = strnlen (src, n);
567 char *res;
569 __bnd_chk_ptr_bounds (dst, n);
570 if (src_size < n)
572 __bnd_chk_ptr_bounds (src, src_size + 1);
573 res = dst + src_size;
575 else
577 __bnd_chk_ptr_bounds (src, src_size);
578 res = dst + n;
581 memcpy (dst, src, src_size);
582 if (n > src_size)
583 memset (dst + src_size, 0, n - src_size);
585 return res;
588 char *
589 __mpx_wrapper_strcpy (char *dst, const char *src)
591 size_t src_size = strlen (src);
593 __bnd_chk_ptr_bounds (dst, src_size + 1);
594 __bnd_chk_ptr_bounds (src, src_size + 1);
596 memcpy (dst, src, src_size + 1);
598 return dst;
601 char *
602 __mpx_wrapper_strncpy (char *dst, const char *src, size_t n)
604 size_t src_size = strnlen (src, n);
606 __bnd_chk_ptr_bounds (dst, n);
607 if (src_size < n)
608 __bnd_chk_ptr_bounds (src, src_size + 1);
609 else
610 __bnd_chk_ptr_bounds (src, src_size);
612 memcpy (dst, src, src_size);
613 if (n > src_size)
614 memset (dst + src_size, 0, n - src_size);
616 return dst;
619 size_t
620 __mpx_wrapper_strlen (const char *s)
622 size_t length = strlen (s);
623 __bnd_chk_ptr_bounds (s, length + 1);
624 return length;