summaryrefslogtreecommitdiff
path: root/libmpx
diff options
context:
space:
mode:
authorienkovich <ienkovich@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-11 14:38:53 +0000
committerienkovich <ienkovich@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-11 14:38:53 +0000
commit3d9a6ba59d71e04cb45d1696c4b815e14f4bed56 (patch)
tree62169eeb0eed7ce16ceda7ca3df1cf922428c590 /libmpx
parent8c3f798620dfc1991a6966610a11d7c07a1d45c0 (diff)
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@231565 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libmpx')
-rw-r--r--libmpx/ChangeLog27
-rw-r--r--libmpx/Makefile.in1
-rw-r--r--libmpx/mpxrt/Makefile.am3
-rw-r--r--libmpx/mpxrt/Makefile.in5
-rw-r--r--libmpx/mpxrt/libmpx.map5
-rw-r--r--libmpx/mpxrt/libtool-version2
-rw-r--r--libmpx/mpxrt/mpxrt.c32
-rw-r--r--libmpx/mpxrt/mpxrt.h75
-rw-r--r--libmpx/mpxwrap/Makefile.am4
-rw-r--r--libmpx/mpxwrap/Makefile.in6
-rw-r--r--libmpx/mpxwrap/libtool-version2
-rw-r--r--libmpx/mpxwrap/mpx_wrappers.c455
12 files changed, 523 insertions, 94 deletions
diff --git a/libmpx/ChangeLog b/libmpx/ChangeLog
index 5e5f77d68a79..93924a8e6ddb 100644
--- a/libmpx/ChangeLog
+++ b/libmpx/ChangeLog
@@ -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
diff --git a/libmpx/Makefile.in b/libmpx/Makefile.in
index ff36a7f9b833..d644af365269 100644
--- a/libmpx/Makefile.in
+++ b/libmpx/Makefile.in
@@ -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@
diff --git a/libmpx/mpxrt/Makefile.am b/libmpx/mpxrt/Makefile.am
index a00a80877929..3280b62a96a6 100644
--- a/libmpx/mpxrt/Makefile.am
+++ b/libmpx/mpxrt/Makefile.am
@@ -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
diff --git a/libmpx/mpxrt/Makefile.in b/libmpx/mpxrt/Makefile.in
index 646f3a95c840..1fdb454f4589 100644
--- a/libmpx/mpxrt/Makefile.in
+++ b/libmpx/mpxrt/Makefile.in
@@ -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
diff --git a/libmpx/mpxrt/libmpx.map b/libmpx/mpxrt/libmpx.map
index 90093b77dee4..1f0fc2c4ce78 100644
--- a/libmpx/mpxrt/libmpx.map
+++ b/libmpx/mpxrt/libmpx.map
@@ -3,3 +3,8 @@ LIBMPX_1.0
local:
*;
};
+LIBMPX_2.0
+{
+ global:
+ get_bd;
+} LIBMPX_1.0;
diff --git a/libmpx/mpxrt/libtool-version b/libmpx/mpxrt/libtool-version
index 5aa6ed72cec2..7d9925549d1c 100644
--- a/libmpx/mpxrt/libtool-version
+++ b/libmpx/mpxrt/libtool-version
@@ -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
diff --git a/libmpx/mpxrt/mpxrt.c b/libmpx/mpxrt/mpxrt.c
index c29c5d9a5010..bcdd3a63bd24 100644
--- a/libmpx/mpxrt/mpxrt.c
+++ b/libmpx/mpxrt/mpxrt.c
@@ -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;
+}
diff --git a/libmpx/mpxrt/mpxrt.h b/libmpx/mpxrt/mpxrt.h
new file mode 100644
index 000000000000..e825d7d9046e
--- /dev/null
+++ b/libmpx/mpxrt/mpxrt.h
@@ -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 ();
diff --git a/libmpx/mpxwrap/Makefile.am b/libmpx/mpxwrap/Makefile.am
index 72abccf8b8be..f24cdc835dc5 100644
--- a/libmpx/mpxwrap/Makefile.am
+++ b/libmpx/mpxwrap/Makefile.am
@@ -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
diff --git a/libmpx/mpxwrap/Makefile.in b/libmpx/mpxwrap/Makefile.in
index 1612ebfb27ee..df1a3347ba0e 100644
--- a/libmpx/mpxwrap/Makefile.in
+++ b/libmpx/mpxwrap/Makefile.in
@@ -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
diff --git a/libmpx/mpxwrap/libtool-version b/libmpx/mpxwrap/libtool-version
index bfe84c8af534..fab30fb091d3 100644
--- a/libmpx/mpxwrap/libtool-version
+++ b/libmpx/mpxwrap/libtool-version
@@ -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
diff --git a/libmpx/mpxwrap/mpx_wrappers.c b/libmpx/mpxwrap/mpx_wrappers.c
index 58670aae4819..ffa7e7ee5fff 100644
--- a/libmpx/mpxwrap/mpx_wrappers.c
+++ b/libmpx/mpxwrap/mpx_wrappers.c
@@ -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);
}
-void *
-__mpx_wrapper_memmove (void *dst, const void *src, size_t n)
+/* 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
{
- 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);
+ 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");
+}
- if (n == 0)
- return ret;
+/* 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;
+}
- __bnd_chk_ptr_bounds (dst, n);
- __bnd_chk_ptr_bounds (src, n);
+/* 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;
+}
- /* 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);
+/* 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
{
- 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;
- }
+ 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
- {
- 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++;
- }
+ {
+ 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 ret;
+ return;
+}
+
+void *
+__mpx_wrapper_memmove (void *dst, const void *src, size_t n)
+{
+ if (n == 0)
+ return dst;
+
+ __bnd_chk_ptr_bounds (dst, n);
+ __bnd_chk_ptr_bounds (src, n);
+
+ 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;
}