Makefile.am (libmpx_la_LDFLAGS): Add -version-info option.

libmpx/

2015-12-11  Tsvetkova Alexandra  <aleksandra.tsvetkova@intel.com>

	* mpxrt/Makefile.am (libmpx_la_LDFLAGS): Add -version-info
	option.
	* libmpxwrap/Makefile.am (libmpx_la_LDFLAGS): Likewise and
	fix include path.
	* libmpx/Makefile.in: Regenerate.
	* mpxrt/Makefile.in: Regenerate.
	* libmpxwrap/Makefile.in: Regenerate.
	* mpxrt/libtool-version: New version.
	* libmpxwrap/libtool-version: Likewise.
	* mpxrt/libmpx.map: Add new version and a new symbol.
	* mpxrt/mpxrt.h: New file.
	* mpxrt/mpxrt.c (NUM_L1_BITS): Moved to mpxrt.h.
	(REG_IP_IDX): Moved to mpxrt.h.
	(REX_PREFIX): Moved to mpxrt.h.
	(XSAVE_OFFSET_IN_FPMEM): Moved to mpxrt.h.
	(MPX_L1_SIZE): Moved to mpxrt.h.
	* libmpxwrap/mpx_wrappers.c (mpx_pointer): New type.
	(mpx_bt_entry): New type.
	(alloc_bt): New function.
	(get_bt): New function.
	(copy_if_possible): New function.
	(copy_if_possible_from_end): New function.
	(move_bounds): New function.
	(__mpx_wrapper_memmove): Use move_bounds to copy bounds.

gcc/testsuite/

2015-12-11  Tsvetkova Alexandra  <aleksandra.tsvetkova@intel.com>

	* gcc.target/i386/mpx/memmove-1.c: New test.
	* gcc.target/i386/mpx/memmove-2.c: New test.

From-SVN: r231565
This commit is contained in:
Tsvetkova Alexandra 2015-12-11 14:38:53 +00:00 committed by Ilya Enkovich
parent a9000e1e2f
commit 653b8b8d89
15 changed files with 685 additions and 94 deletions

View File

@ -1,3 +1,8 @@
2015-12-11 Tsvetkova Alexandra <aleksandra.tsvetkova@intel.com>
* gcc.target/i386/mpx/memmove-1.c: New test.
* gcc.target/i386/mpx/memmove-2.c: New test.
2015-12-11 Nathan Sidwell <nathan@acm.org>
* gcc.target/nvptx/ary-init.c: Repair dg_final syntax.

View File

@ -0,0 +1,117 @@
/* { dg-do run } */
/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
#include <stdint.h>
#include <string.h>
#include "mpx-check.h"
#ifdef __i386__
/* i386 directory size is 4MB. */
#define MPX_NUM_L2_BITS 10
#define MPX_NUM_IGN_BITS 2
#else /* __i386__ */
/* x86_64 directory size is 2GB. */
#define MPX_NUM_L2_BITS 17
#define MPX_NUM_IGN_BITS 3
#endif /* !__i386__ */
/* bt_num_of_elems is the number of elements in bounds table. */
unsigned long bt_num_of_elems = (1UL << MPX_NUM_L2_BITS);
/* Function to test MPX wrapper of memmove function.
src_bigger_dst determines which address is bigger, can be 0 or 1.
src_bt_index and dst_bt index are bt_indexes
from the beginning of the page.
bd_index_end is the bd index of the last element of src if we define
bd index of the first element as 0.
src_bt index_end is bt index of the last element of src.
pointers inside determines if array being copied includes pointers
src_align and dst_align are alignments of src and dst.
Arrays may contain unaligned pointers. */
int
test (int src_bigger_dst, int src_bt_index, int dst_bt_index,
int bd_index_end, int src_bt_index_end, int pointers_inside,
int src_align, int dst_align)
{
const int n =
src_bt_index_end - src_bt_index + bd_index_end * bt_num_of_elems;
if (n < 0)
{
return 0;
}
const int num_of_pointers = (bd_index_end + 2) * bt_num_of_elems;
void **arr = 0;
posix_memalign ((void **) (&arr),
1UL << (MPX_NUM_L2_BITS + MPX_NUM_IGN_BITS),
num_of_pointers * sizeof (void *));
void **src = arr, **dst = arr;
if ((src_bigger_dst) && (src_bt_index < dst_bt_index))
src_bt_index += bt_num_of_elems;
if (!(src_bigger_dst) && (src_bt_index > dst_bt_index))
dst_bt_index += bt_num_of_elems;
src += src_bt_index;
dst += dst_bt_index;
char *realign = (char *) src;
realign += src_align;
src = (void **) realign;
realign = (char *) dst;
realign += src_align;
dst = (void **) realign;
if (pointers_inside)
{
for (int i = 0; i < n; i++)
src[i] = __bnd_set_ptr_bounds (arr + i, i * sizeof (void *) + 1);
}
memmove (dst, src, n * sizeof (void *));
if (pointers_inside)
{
for (int i = 0; i < n; i++)
{
if (dst[i] != arr + i)
abort ();
if (__bnd_get_ptr_lbound (dst[i]) != arr + i)
abort ();
if (__bnd_get_ptr_ubound (dst[i]) != arr + 2 * i)
abort ();
}
}
free (arr);
return 0;
}
/* Call testall to test common cases of memmove for MPX. */
void
testall ()
{
int align[3];
align[0] = 0;
align[1] = 1;
align[2] = 7;
for (int pointers_inside = 0; pointers_inside < 2; pointers_inside++)
for (int src_bigger_dst = 0; src_bigger_dst < 2; src_bigger_dst++)
for (int src_align = 0; src_align < 3; src_align ++)
for (int dst_align = 0; dst_align < 3; dst_align ++)
for (int pages = 0; pages < 4; pages++)
{
test (src_bigger_dst, 1, 2, pages, 1, pointers_inside,
align[src_align], align[dst_align]);
test (src_bigger_dst, 1, 2, pages, 2, pointers_inside,
align[src_align], align[dst_align]);
test (src_bigger_dst, 2, 1, pages, 12, pointers_inside,
align[src_align], align[dst_align]);
test (src_bigger_dst, 2, 1, pages, 1, pointers_inside,
align[src_align], align[dst_align]);
test (src_bigger_dst, 2, 3, pages, 12, pointers_inside,
align[src_align], align[dst_align]);
test (src_bigger_dst, 1, bt_num_of_elems - 2, pages, 2,
pointers_inside, align[src_align], align[dst_align]);
}
};
int
mpx_test (int argc, const char **argv)
{
testall ();
return 0;
}

View File

@ -0,0 +1,40 @@
/* { dg-do run } */
/* { dg-options "-fcheck-pointer-bounds -mmpx" } */
#include <stdint.h>
#include <string.h>
#include "mpx-check.h"
#ifdef __i386__
/* i386 directory size is 4MB. */
#define MPX_NUM_L2_BITS 10
#define MPX_NUM_IGN_BITS 2
#else /* __i386__ */
/* x86_64 directory size is 2GB. */
#define MPX_NUM_L2_BITS 17
#define MPX_NUM_IGN_BITS 3
#endif /* !__i386__ */
/* bt_num_of_elems is the number of elements in bounds table. */
unsigned long bt_num_of_elems = (1UL << MPX_NUM_L2_BITS);
/* Function to test MPX wrapper of memmove function.
Check case with no BT allocated for data. */
int
mpx_test (int argc, const char **argv)
{
void **arr = 0;
posix_memalign ((void **) (&arr),
1UL << (MPX_NUM_L2_BITS + MPX_NUM_IGN_BITS),
2 * bt_num_of_elems * sizeof (void *));
void **src = arr, **dst = arr, **ptr = arr;
src += 10;
dst += 1;
ptr += bt_num_of_elems + 100;
ptr[0] = __bnd_set_ptr_bounds (arr + 1, sizeof (void *) + 1);
memmove (dst, src, 5 * sizeof (void *));
return 0;
}

View File

@ -1,3 +1,30 @@
2015-12-11 Tsvetkova Alexandra <aleksandra.tsvetkova@intel.com>
* mpxrt/Makefile.am (libmpx_la_LDFLAGS): Add -version-info
option.
* libmpxwrap/Makefile.am (libmpx_la_LDFLAGS): Likewise and
fix include path.
* libmpx/Makefile.in: Regenerate.
* mpxrt/Makefile.in: Regenerate.
* libmpxwrap/Makefile.in: Regenerate.
* mpxrt/libtool-version: New version.
* libmpxwrap/libtool-version: Likewise.
* mpxrt/libmpx.map: Add new version and a new symbol.
* mpxrt/mpxrt.h: New file.
* mpxrt/mpxrt.c (NUM_L1_BITS): Moved to mpxrt.h.
(REG_IP_IDX): Moved to mpxrt.h.
(REX_PREFIX): Moved to mpxrt.h.
(XSAVE_OFFSET_IN_FPMEM): Moved to mpxrt.h.
(MPX_L1_SIZE): Moved to mpxrt.h.
* libmpxwrap/mpx_wrappers.c (mpx_pointer): New type.
(mpx_bt_entry): New type.
(alloc_bt): New function.
(get_bt): New function.
(copy_if_possible): New function.
(copy_if_possible_from_end): New function.
(move_bounds): New function.
(__mpx_wrapper_memmove): Use move_bounds to copy bounds.
2015-10-15 Ilya Enkovich <enkovich.gnu@gmail.com>
PR other/66887

View File

@ -228,7 +228,6 @@ install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
link_libmpx = @link_libmpx@
link_mpx = @link_mpx@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@

View File

@ -13,7 +13,8 @@ libmpx_la_SOURCES = mpxrt.c mpxrt-utils.c
libmpx_la_CFLAGS = -fPIC
libmpx_la_DEPENDENCIES = libmpx.map
libmpx_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libmpx.map $(link_libmpx)
libmpx_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libmpx.map $(link_libmpx) \
-version-info `grep -v '^\#' $(srcdir)/libtool-version`
mpxrt.lo: mpxrt-utils.h
mpxrt-utils.lo: mpxrt-utils.h

View File

@ -222,7 +222,6 @@ install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
link_libmpx = @link_libmpx@
link_mpx = @link_mpx@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
@ -257,7 +256,9 @@ ACLOCAL_AMFLAGS = -I $(top_srcdir) -I $(top_srcdir)/config
@LIBMPX_SUPPORTED_TRUE@libmpx_la_SOURCES = mpxrt.c mpxrt-utils.c
@LIBMPX_SUPPORTED_TRUE@libmpx_la_CFLAGS = -fPIC
@LIBMPX_SUPPORTED_TRUE@libmpx_la_DEPENDENCIES = libmpx.map
@LIBMPX_SUPPORTED_TRUE@libmpx_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libmpx.map $(link_libmpx)
@LIBMPX_SUPPORTED_TRUE@libmpx_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libmpx.map $(link_libmpx) \
@LIBMPX_SUPPORTED_TRUE@ -version-info `grep -v '^\#' $(srcdir)/libtool-version`
# Work around what appears to be a GNU make bug handling MAKEFLAGS
# values defined in terms of make variables, as is the case for CC and

View File

@ -3,3 +3,8 @@ LIBMPX_1.0
local:
*;
};
LIBMPX_2.0
{
global:
get_bd;
} LIBMPX_1.0;

View File

@ -3,4 +3,4 @@
# a separate file so that version updates don't involve re-running
# automake.
# CURRENT:REVISION:AGE
1:0:0
2:0:0

View File

@ -51,34 +51,11 @@
#include <sys/prctl.h>
#include <cpuid.h>
#include "mpxrt-utils.h"
#ifdef __i386__
/* i386 directory size is 4MB */
#define NUM_L1_BITS 20
#define REG_IP_IDX REG_EIP
#define REX_PREFIX
#define XSAVE_OFFSET_IN_FPMEM sizeof (struct _libc_fpstate)
#else /* __i386__ */
/* x86_64 directory size is 2GB */
#define NUM_L1_BITS 28
#define REG_IP_IDX REG_RIP
#define REX_PREFIX "0x48, "
#define XSAVE_OFFSET_IN_FPMEM 0
#endif /* !__i386__ */
#include "mpxrt.h"
#define MPX_ENABLE_BIT_NO 0
#define BNDPRESERVE_BIT_NO 1
const size_t MPX_L1_SIZE = (1UL << NUM_L1_BITS) * sizeof (void *);
struct xsave_hdr_struct
{
uint64_t xstate_bv;
@ -508,3 +485,10 @@ mpxrt_cleanup (void)
__mpxrt_utils_free ();
process_specific_finish ();
}
/* Get address of bounds directory. */
void *
get_bd ()
{
return l1base;
}

75
libmpx/mpxrt/mpxrt.h Normal file
View File

@ -0,0 +1,75 @@
/* mpxrt.h -*-C++-*-
*
*************************************************************************
*
* @copyright
* Copyright (C) 2015, Intel Corporation
* All rights reserved.
*
* @copyright
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* @copyright
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************/
#ifdef __i386__
/* i386 directory size is 4MB. */
#define NUM_L1_BITS 20
#define NUM_L2_BITS 10
#define NUM_IGN_BITS 2
#define MPX_L1_ADDR_MASK 0xfffff000UL
#define MPX_L2_ADDR_MASK 0xfffffffcUL
#define MPX_L2_VALID_MASK 0x00000001UL
#define REG_IP_IDX REG_EIP
#define REX_PREFIX
#define XSAVE_OFFSET_IN_FPMEM sizeof (struct _libc_fpstate)
#else /* __i386__ */
/* x86_64 directory size is 2GB. */
#define NUM_L1_BITS 28
#define NUM_L2_BITS 17
#define NUM_IGN_BITS 3
#define MPX_L1_ADDR_MASK 0xfffffffffffff000ULL
#define MPX_L2_ADDR_MASK 0xfffffffffffffff8ULL
#define MPX_L2_VALID_MASK 0x0000000000000001ULL
#define REG_IP_IDX REG_RIP
#define REX_PREFIX "0x48, "
#define XSAVE_OFFSET_IN_FPMEM 0
#endif /* !__i386__ */
#define MPX_L1_SIZE ((1UL << NUM_L1_BITS) * sizeof (void *))
/* Get address of bounds directory. */
void *
get_bd ();

View File

@ -1,4 +1,5 @@
ALCLOCAL_AMFLAGS = -I .. -I ../config
AM_CPPFLAGS = -I $(top_srcdir)
# May be used by toolexeclibdir.
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
@ -6,7 +7,8 @@ gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
libmpxwrappers_la_CFLAGS = -fcheck-pointer-bounds -mmpx -fno-chkp-check-read \
-fno-chkp-check-write -fno-chkp-use-wrappers -fPIC
libmpxwrappers_la_DEPENDENCIES = libmpxwrappers.map
libmpxwrappers_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libmpxwrappers.map
libmpxwrappers_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libmpxwrappers.map \
-version-info `grep -v '^\#' $(srcdir)/libtool-version`
toolexeclib_LTLIBRARIES = libmpxwrappers.la

View File

@ -221,7 +221,6 @@ install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
link_libmpx = @link_libmpx@
link_mpx = @link_mpx@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
@ -247,6 +246,7 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
ALCLOCAL_AMFLAGS = -I .. -I ../config
AM_CPPFLAGS = -I $(top_srcdir)
# May be used by toolexeclibdir.
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
@ -254,7 +254,9 @@ libmpxwrappers_la_CFLAGS = -fcheck-pointer-bounds -mmpx -fno-chkp-check-read \
-fno-chkp-check-write -fno-chkp-use-wrappers -fPIC
libmpxwrappers_la_DEPENDENCIES = libmpxwrappers.map
libmpxwrappers_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libmpxwrappers.map
libmpxwrappers_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libmpxwrappers.map \
-version-info `grep -v '^\#' $(srcdir)/libtool-version`
toolexeclib_LTLIBRARIES = libmpxwrappers.la
libmpxwrappers_la_SOURCES = mpx_wrappers.c

View File

@ -3,4 +3,4 @@
# a separate file so that version updates don't involve re-running
# automake.
# CURRENT:REVISION:AGE
1:0:0
2:0:0

View File

@ -26,6 +26,8 @@
#include "stdlib.h"
#include "string.h"
#include <sys/mman.h>
#include <stdint.h>
#include "mpxrt/mpxrt.h"
void *
__mpx_wrapper_malloc (size_t size)
@ -88,75 +90,406 @@ __mpx_wrapper_bzero (void *dst, size_t len)
__mpx_wrapper_memset (dst, 0, len);
}
/* The mpx_pointer type is used for getting bits
for bt_index (index in bounds table) and
bd_index (index in bounds directory). */
typedef union
{
struct
{
unsigned long ignored:NUM_IGN_BITS;
unsigned long l2entry:NUM_L2_BITS;
unsigned long l1index:NUM_L1_BITS;
};
void *pointer;
} mpx_pointer;
/* The mpx_bt_entry struct represents a cell in bounds table.
lb is the lower bound, ub is the upper bound,
p is the stored pointer. */
struct mpx_bt_entry
{
void *lb;
void *ub;
void *p;
void *reserved;
};
/* A special type for bd is needed because bt addresses can be modified. */
typedef struct mpx_bt_entry * volatile * bd_type;
/* Function alloc_bt is used for allocating bounds table
for the destination pointers if we don't have one.
We generate a bounds store for some pointer belonging
to that table and kernel allocates the table for us. */
static inline void __attribute__ ((bnd_legacy))
alloc_bt (void *ptr)
{
__asm__ __volatile__ ("bndstx %%bnd0, (%0,%0)"::"r" (ptr):"%bnd0");
}
/* get_bt returns address of bounds table that should
exist at BD[BD_INDEX]. If there is no address or the address is not valid,
we try to allocate a valid table.
If we succeed in getting bt, its address will be returned.
If we can't get a valid bt, NULL will be returned. */
__attribute__ ((bnd_legacy)) static inline struct mpx_bt_entry *
get_bt (unsigned bd_index, bd_type bd)
{
struct mpx_bt_entry *bt = (struct mpx_bt_entry *) ((uintptr_t) bd[bd_index]
& MPX_L2_ADDR_MASK);
if (!(bt) || !((uintptr_t) bd[bd_index] & MPX_L2_VALID_MASK))
{
mpx_pointer ptr;
ptr.l1index = bd_index;
/* If we don't have BT, allocate it. */
alloc_bt (ptr.pointer);
bt = (struct mpx_bt_entry *) ((uintptr_t) bd[bd_index]
& MPX_L2_ADDR_MASK);
if (!(bt) || !((uintptr_t) bd[bd_index] & MPX_L2_VALID_MASK))
return NULL;
}
return bt;
}
/* Function copy_if_possible moves elements from *FROM to *TO.
If ELEMS is less then the ELEMS_TO_COPY (elements we can copy),
it copies ELEMS elements and returns 0.
Otherwise, it copies ELEMS_TO_COPY elements and returns 1. */
__attribute__ ((bnd_legacy)) static inline int
copy_if_possible (int elems, int elems_to_copy, struct mpx_bt_entry *from,
struct mpx_bt_entry *to)
{
if (elems < elems_to_copy)
memmove (to, from, elems * sizeof (struct mpx_bt_entry));
else
{
memmove (to, from, elems_to_copy * sizeof (struct mpx_bt_entry));
return 1;
}
return 0;
}
/* Function copy_if_possible_from_end moves elements ending at *SRC_END
to the place where they will end at *DST_END.
If ELEMS is less then the ELEMS_TO_COPY (elements we can copy),
function copies ELEMS elements and returns 0.
Otherwise, it copies ELEMS_TO_COPY elements and returns 1. */
__attribute__ ((bnd_legacy)) static inline int
copy_if_possible_from_end (int elems, int elems_to_copy, struct mpx_bt_entry
*src_end, struct mpx_bt_entry *dst_end)
{
if (elems < elems_to_copy)
memmove (dst_end - elems, src_end - elems,
elems * sizeof (struct mpx_bt_entry));
else
{
memmove (dst_end - elems_to_copy,
src_end - elems_to_copy,
elems_to_copy * sizeof (struct mpx_bt_entry));
return 1;
}
return 0;
}
/* move_bounds function copies bounds for N bytes from bt of SRC to bt of DST.
It also copies bounds for all pointers inside.
There are 3 parts of the algorithm:
1) We copy everything till the end of the first bounds table of SRC
2) In loop we copy whole bound tables till the second-last one
3) Data in the last bounds table is copied separately, after the loop.
If one of bound tables in SRC doesn't exist,
we skip it because there are no pointers.
Depending on the arrangement of SRC and DST we copy from the beginning
or from the end. */
__attribute__ ((bnd_legacy)) static void
move_bounds (void *dst, const void *src, size_t n)
{
bd_type bd = (bd_type)get_bd ();
if (!(bd))
return;
/* We get indexes for all tables and number of elements for BT. */
unsigned long bt_num_of_elems = (1UL << NUM_L2_BITS);
mpx_pointer addr_src, addr_dst, addr_src_end, addr_dst_end;
addr_src.pointer = (char *) src;
addr_dst.pointer = (char *) dst;
addr_src_end.pointer = (char *) src + n - 1;
addr_dst_end.pointer = (char *) dst + n - 1;
unsigned dst_bd_index = addr_dst.l1index;
unsigned src_bd_index = addr_src.l1index;
unsigned dst_bt_index = addr_dst.l2entry;
unsigned src_bt_index = addr_src.l2entry;
unsigned dst_bd_index_end = addr_dst_end.l1index;
unsigned src_bd_index_end = addr_src_end.l1index;
unsigned dst_bt_index_end = addr_dst_end.l2entry;
unsigned src_bt_index_end = addr_src_end.l2entry;
int elems_to_copy = src_bt_index_end - src_bt_index + 1 + (src_bd_index_end
- src_bd_index) * bt_num_of_elems;
struct mpx_bt_entry *bt_src, *bt_dst;
uintptr_t bt_valid;
/* size1 and size2 will be used to find out what portions
can be used to copy data. */
int size1_elem, size2_elem, size1_bytes, size2_bytes;
/* Copy from the beginning. */
if (((char *) src - (char *) dst) > 0)
{
/* Copy everything till the end of the first bounds table (src) */
bt_src = (struct mpx_bt_entry *) ((uintptr_t) bd[src_bd_index]
& MPX_L2_ADDR_MASK);
bt_valid = (uintptr_t) bd[src_bd_index] & MPX_L2_VALID_MASK;
/* We can copy the whole preliminary piece of data. */
if (src_bt_index > dst_bt_index)
{
size1_elem = src_bt_index - dst_bt_index;
size2_elem = bt_num_of_elems - size1_elem;
size1_bytes = size1_elem * sizeof (struct mpx_bt_entry);
size2_bytes = size2_elem * sizeof (struct mpx_bt_entry);
/* Check we have bounds to copy. */
if (bt_src && bt_valid)
{
bt_dst = get_bt (dst_bd_index, bd);
if (!bt_dst)
return;
if (copy_if_possible (bt_num_of_elems - src_bt_index,
elems_to_copy, &(bt_src[src_bt_index]),
&(bt_dst[dst_bt_index])))
return;
}
elems_to_copy -= bt_num_of_elems - src_bt_index;
}
/* We have to copy preliminary data in two parts. */
else
{
size2_elem = dst_bt_index - src_bt_index;
size1_elem = bt_num_of_elems - size2_elem;
size1_bytes = size1_elem * sizeof (struct mpx_bt_entry);
size2_bytes = size2_elem * sizeof (struct mpx_bt_entry);
/* Check we have bounds to copy. */
if (bt_src && bt_valid)
{
bt_dst = get_bt (dst_bd_index, bd);
if (!bt_dst)
return;
if (copy_if_possible (bt_num_of_elems - dst_bt_index,
elems_to_copy, &(bt_src[src_bt_index]),
&(bt_dst[dst_bt_index])))
return;
elems_to_copy -= bt_num_of_elems - dst_bt_index;
dst_bd_index++;
bt_dst = get_bt (dst_bd_index, bd);
if (!bt_dst)
return;
if (copy_if_possible (size2_elem, elems_to_copy,
&(bt_src[size1_elem]), &(bt_dst[0])))
return;
elems_to_copy -= size2_elem;
}
else
elems_to_copy -= bt_num_of_elems - src_bt_index;
}
src_bd_index++;
/* For each bounds table check if it's valid and move it. */
for (; src_bd_index < src_bd_index_end; src_bd_index++)
{
bt_src = (struct mpx_bt_entry *) ((uintptr_t) bd[src_bd_index]
& MPX_L2_ADDR_MASK);
bt_valid = (uintptr_t) bd[src_bd_index] & MPX_L2_VALID_MASK;
/* Check we have bounds to copy. */
if (!bt_src || !bt_valid)
dst_bd_index++;
else
{
bt_dst = get_bt (dst_bd_index, bd);
if (!bt_dst)
return;
memmove (&(bt_dst[size2_elem]), &(bt_src[0]), size1_bytes);
dst_bd_index++;
bt_dst = get_bt (dst_bd_index, bd);
if (!bt_dst)
return;
memmove (&(bt_dst[0]), &(bt_src[size1_elem]), size2_bytes);
}
elems_to_copy -= bt_num_of_elems;
}
/* Now we have the last page that may be not full
we copy it separately. */
if (elems_to_copy > 0)
{
bt_src = (struct mpx_bt_entry *) ((uintptr_t) bd[src_bd_index]
& MPX_L2_ADDR_MASK);
bt_valid = (uintptr_t) bd[src_bd_index] & MPX_L2_VALID_MASK;
/* Check we have bounds to copy. */
if (bt_src && bt_valid)
{
bt_dst = get_bt (dst_bd_index, bd);
if (!bt_dst)
return;
if (copy_if_possible (size1_elem, elems_to_copy, &(bt_src[0]),
&(bt_dst[size2_elem])))
return;
elems_to_copy -= size1_elem;
dst_bd_index++;
bt_dst = get_bt (dst_bd_index, bd);
if (!bt_dst)
return;
memmove (&(bt_dst[0]), &(bt_src[size1_elem]),
elems_to_copy * sizeof (struct mpx_bt_entry));
}
}
}
/* Copy from the end. */
else
{
/* Copy everything till the end of the first bounds table (src) */
bt_src = (struct mpx_bt_entry *) ((uintptr_t) bd[src_bd_index_end]
& MPX_L2_ADDR_MASK);
bt_valid = (uintptr_t) bd[src_bd_index_end] & MPX_L2_VALID_MASK;
if (src_bt_index_end <= dst_bt_index_end)
/* We can copy the whole preliminary piece of data. */
{
size2_elem = dst_bt_index_end - src_bt_index_end;
size1_elem = bt_num_of_elems - size2_elem;
size1_bytes = size1_elem * sizeof (struct mpx_bt_entry);
size2_bytes = size2_elem * sizeof (struct mpx_bt_entry);
/* Check we have bounds to copy. */
if (bt_src && bt_valid)
{
bt_dst = get_bt (dst_bd_index_end, bd);
if (!bt_dst)
return;
if (copy_if_possible_from_end (src_bt_index_end + 1,
elems_to_copy, &(bt_src[src_bt_index_end + 1]),
&(bt_dst[dst_bt_index_end + 1])))
return;
}
elems_to_copy -= src_bt_index_end + 1;
}
/* We have to copy preliminary data in two parts. */
else
{
size1_elem = src_bt_index_end - dst_bt_index_end;
size2_elem = bt_num_of_elems - size1_elem;
size1_bytes = size1_elem * sizeof (struct mpx_bt_entry);
size2_bytes = size2_elem * sizeof (struct mpx_bt_entry);
/* Check we have bounds to copy. */
if (bt_src && bt_valid)
{
bt_dst = get_bt (dst_bd_index_end, bd);
if (!bt_dst)
return;
if (copy_if_possible_from_end (dst_bt_index_end + 1,
elems_to_copy, &(bt_src[src_bt_index_end + 1]),
&(bt_dst[dst_bt_index_end + 1])))
return;
elems_to_copy -= dst_bt_index_end + 1;
dst_bd_index_end--;
bt_dst = get_bt (dst_bd_index_end, bd);
if (!bt_dst)
return;
if (copy_if_possible_from_end (size1_elem, elems_to_copy,
&(bt_src[size1_elem]), &(bt_dst[bt_num_of_elems])))
return;
elems_to_copy -= size1_elem;
}
else
elems_to_copy -= src_bt_index_end + 1;
}
src_bd_index_end--;
/* For each bounds table we check if there are valid pointers inside.
If there are some, we copy table in pre-counted portions. */
for (; src_bd_index_end > src_bd_index; src_bd_index_end--)
{
bt_src = (struct mpx_bt_entry *) ((uintptr_t) bd[src_bd_index_end]
& MPX_L2_ADDR_MASK);
bt_valid = (uintptr_t) bd[src_bd_index_end] & MPX_L2_VALID_MASK;
/* Check we have bounds to copy. */
if (!bt_src || !bt_valid)
dst_bd_index_end--;
else
{
bt_dst = get_bt (dst_bd_index_end, bd);
if (!bt_dst)
return;
memmove (&(bt_dst[0]), &(bt_src[size1_elem]), size2_bytes);
dst_bd_index_end--;
bt_dst = get_bt (dst_bd_index_end, bd);
if (!bt_dst)
return;
memmove (&(bt_dst[size2_elem]), &(bt_src[0]), size1_bytes);
}
elems_to_copy -= bt_num_of_elems;
}
/* Now we have the last page that may be not full
we copy it separately. */
if (elems_to_copy > 0)
{
bt_src = (struct mpx_bt_entry *) ((uintptr_t) bd[src_bd_index_end]
& MPX_L2_ADDR_MASK);
bt_valid = (uintptr_t) bd[src_bd_index_end] & MPX_L2_VALID_MASK;
/* Check we have bounds to copy. */
if (bt_src && bt_valid)
{
bt_dst = get_bt (dst_bd_index_end, bd);
if (!bt_dst)
return;
if (copy_if_possible_from_end (size2_elem, elems_to_copy,
&(bt_src[bt_num_of_elems]), &(bt_dst[size2_elem])))
return;
elems_to_copy -= size2_elem;
dst_bd_index_end--;
bt_dst = get_bt (dst_bd_index_end, bd);
if (!bt_dst)
return;
memmove (&(bt_dst[dst_bt_index]), &(bt_src[src_bt_index]),
elems_to_copy * sizeof (struct mpx_bt_entry));
}
}
}
return;
}
void *
__mpx_wrapper_memmove (void *dst, const void *src, size_t n)
{
const char *s = (const char*)src;
char *d = (char*)dst;
void *ret = dst;
size_t offset_src = ((size_t) s) & (sizeof (void *) - 1);
size_t offset_dst = ((size_t) d) & (sizeof (void *) - 1);
if (n == 0)
return ret;
return dst;
__bnd_chk_ptr_bounds (dst, n);
__bnd_chk_ptr_bounds (src, n);
/* Different alignment means that even if
pointers exist in memory, we don't how
pointers are aligned and therefore cann't
copy bounds anyway. */
if (offset_src != offset_dst)
memmove (dst, src, n);
else
{
if (s < d)
{
d += n;
s += n;
offset_src = (offset_src + n) & (sizeof (void *) -1);
while (n-- && offset_src--)
*--d = *--s;
n++;
if (!n)
return ret;
void **d1 = (void **)d;
void **s1 = (void **)s;
/* This loop will also copy bounds. */
while (n >= sizeof (void *))
{
n -= sizeof (void *);
*--d1 = *--s1;
}
s = (char *)s1;
d = (char *)d1;
while (n--)
*--d = *--s;
}
else
{
offset_src = sizeof (void *) - offset_src;
while (n-- && offset_src--)
*d++ = *s++;
n++;
if (!n)
return ret;
void **d1 = (void **)d;
void **s1 = (void **)s;
/* This loop will also copy bounds. */
while (n >= sizeof (void *))
{
n -= sizeof (void *);
*d1++ = *s1++;
}
s = (char *)s1;
d = (char *)d1;
while (n--)
*d++ = *s++;
}
}
return ret;
memmove (dst, src, n);
/* Not necessary to copy bounds if size is less then size of pointer
or SRC==DST. */
if ((n >= sizeof (void *)) && (src != dst))
move_bounds (dst, src, n);
return dst;
}