From 109719ebd4ee99f377256bd262941358c89a9635 Mon Sep 17 00:00:00 2001 From: Ilya Enkovich Date: Wed, 30 Oct 2013 09:06:20 +0000 Subject: [PATCH] builtin-types.def (BT_FN_VOID_CONST_PTR): New. * builtin-types.def (BT_FN_VOID_CONST_PTR): New. (BT_FN_PTR_CONST_PTR): New. (BT_FN_CONST_PTR_CONST_PTR): New. (BT_FN_PTR_CONST_PTR_SIZE): New. (BT_FN_PTR_CONST_PTR_CONST_PTR): New. (BT_FN_VOID_PTRPTR_CONST_PTR): New. (BT_FN_VOID_CONST_PTR_SIZE): New. (BT_FN_PTR_CONST_PTR_CONST_PTR_SIZE): New. * chkp-builtins.def: New. * builtins.def: include chkp-builtins.def. (DEF_CHKP_BUILTIN): New. * builtins.c (expand_builtin): Support BUILT_IN_CHKP_INIT_PTR_BOUNDS, BUILT_IN_CHKP_NULL_PTR_BOUNDS, BUILT_IN_CHKP_COPY_PTR_BOUNDS, BUILT_IN_CHKP_CHECK_PTR_LBOUNDS, BUILT_IN_CHKP_CHECK_PTR_UBOUNDS, BUILT_IN_CHKP_CHECK_PTR_BOUNDS, BUILT_IN_CHKP_SET_PTR_BOUNDS, BUILT_IN_CHKP_NARROW_PTR_BOUNDS, BUILT_IN_CHKP_STORE_PTR_BOUNDS, BUILT_IN_CHKP_GET_PTR_LBOUND, BUILT_IN_CHKP_GET_PTR_UBOUND, BUILT_IN_CHKP_BNDMK, BUILT_IN_CHKP_BNDSTX, BUILT_IN_CHKP_BNDCL, BUILT_IN_CHKP_BNDCU, BUILT_IN_CHKP_BNDLDX, BUILT_IN_CHKP_BNDRET, BUILT_IN_CHKP_INTERSECT, BUILT_IN_CHKP_ARG_BND, BUILT_IN_CHKP_NARROW, BUILT_IN_CHKP_EXTRACT_LOWER, BUILT_IN_CHKP_EXTRACT_UPPER. * common.opt (fcheck-pointer-bounds): New. * toplev.c (process_options): Check Pointer Bounds Checker is supported. * doc/extend.texi: Document Pointer Bounds Checker built-in functions. From-SVN: r204196 --- gcc/ChangeLog | 27 +++++++ gcc/builtin-types.def | 8 ++ gcc/builtins.c | 58 +++++++++++++- gcc/builtins.def | 9 +++ gcc/common.opt | 5 ++ gcc/doc/extend.texi | 171 ++++++++++++++++++++++++++++++++++++++++++ gcc/toplev.c | 9 +++ 7 files changed, 286 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1c00e3c28a5..6756d107a0a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,30 @@ +2013-10-29 Ilya Enkovich + + * builtin-types.def (BT_FN_VOID_CONST_PTR): New. + (BT_FN_PTR_CONST_PTR): New. + (BT_FN_CONST_PTR_CONST_PTR): New. + (BT_FN_PTR_CONST_PTR_SIZE): New. + (BT_FN_PTR_CONST_PTR_CONST_PTR): New. + (BT_FN_VOID_PTRPTR_CONST_PTR): New. + (BT_FN_VOID_CONST_PTR_SIZE): New. + (BT_FN_PTR_CONST_PTR_CONST_PTR_SIZE): New. + * chkp-builtins.def: New. + * builtins.def: include chkp-builtins.def. + (DEF_CHKP_BUILTIN): New. + * builtins.c (expand_builtin): Support BUILT_IN_CHKP_INIT_PTR_BOUNDS, + BUILT_IN_CHKP_NULL_PTR_BOUNDS, BUILT_IN_CHKP_COPY_PTR_BOUNDS, + BUILT_IN_CHKP_CHECK_PTR_LBOUNDS, BUILT_IN_CHKP_CHECK_PTR_UBOUNDS, + BUILT_IN_CHKP_CHECK_PTR_BOUNDS, BUILT_IN_CHKP_SET_PTR_BOUNDS, + BUILT_IN_CHKP_NARROW_PTR_BOUNDS, BUILT_IN_CHKP_STORE_PTR_BOUNDS, + BUILT_IN_CHKP_GET_PTR_LBOUND, BUILT_IN_CHKP_GET_PTR_UBOUND, + BUILT_IN_CHKP_BNDMK, BUILT_IN_CHKP_BNDSTX, BUILT_IN_CHKP_BNDCL, + BUILT_IN_CHKP_BNDCU, BUILT_IN_CHKP_BNDLDX, BUILT_IN_CHKP_BNDRET, + BUILT_IN_CHKP_INTERSECT, BUILT_IN_CHKP_ARG_BND, BUILT_IN_CHKP_NARROW, + BUILT_IN_CHKP_EXTRACT_LOWER, BUILT_IN_CHKP_EXTRACT_UPPER. + * common.opt (fcheck-pointer-bounds): New. + * toplev.c (process_options): Check Pointer Bounds Checker is supported. + * doc/extend.texi: Document Pointer Bounds Checker built-in functions. + 2013-10-30 Ilya Enkovich * target.def (builtin_chkp_function): New. diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index 3deedba5b78..1f9ae4e2317 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -226,6 +226,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_DFLOAT64, BT_DFLOAT64, BT_DFLOAT64) DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_DFLOAT128, BT_DFLOAT128, BT_DFLOAT128) DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, BT_VOID, BT_PTR_PTR) +DEF_FUNCTION_TYPE_1 (BT_FN_VOID_CONST_PTR, BT_VOID, BT_CONST_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT) DEF_FUNCTION_TYPE_1 (BT_FN_ULONG_ULONG, BT_ULONG, BT_ULONG) DEF_FUNCTION_TYPE_1 (BT_FN_ULONGLONG_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG) @@ -233,6 +234,8 @@ DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_UINT16, BT_UINT16, BT_UINT16) DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT32, BT_UINT32, BT_UINT32) DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_UINT64, BT_UINT64, BT_UINT64) DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_INT, BT_BOOL, BT_INT) +DEF_FUNCTION_TYPE_1 (BT_FN_PTR_CONST_PTR, BT_PTR, BT_CONST_PTR) +DEF_FUNCTION_TYPE_1 (BT_FN_CONST_PTR_CONST_PTR, BT_CONST_PTR, BT_CONST_PTR) DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR) @@ -346,6 +349,10 @@ DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_VPTR, BT_BOOL, BT_SIZE, BT_CONST_VOLATILE_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_INT_BOOL, BT_BOOL, BT_INT, BT_BOOL) DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT_UINT, BT_VOID, BT_UINT, BT_UINT) +DEF_FUNCTION_TYPE_2 (BT_FN_PTR_CONST_PTR_SIZE, BT_PTR, BT_CONST_PTR, BT_SIZE) +DEF_FUNCTION_TYPE_2 (BT_FN_PTR_CONST_PTR_CONST_PTR, BT_PTR, BT_CONST_PTR, BT_CONST_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTRPTR_CONST_PTR, BT_VOID, BT_PTR_PTR, BT_CONST_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_CONST_PTR_SIZE, BT_VOID, BT_CONST_PTR, BT_SIZE) DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR) @@ -428,6 +435,7 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I2_INT, BT_VOID, BT_VOLATILE_PTR, BT_I2, BT DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I4_INT, BT_VOID, BT_VOLATILE_PTR, BT_I4, BT_INT) DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I8_INT, BT_VOID, BT_VOLATILE_PTR, BT_I8, BT_INT) DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I16_INT, BT_VOID, BT_VOLATILE_PTR, BT_I16, BT_INT) +DEF_FUNCTION_TYPE_3 (BT_FN_PTR_CONST_PTR_CONST_PTR_SIZE, BT_PTR, BT_CONST_PTR, BT_CONST_PTR, BT_SIZE) DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR, BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR) diff --git a/gcc/builtins.c b/gcc/builtins.c index cfe9be533b5..1b085450d9e 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -5646,7 +5646,18 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, && fcode != BUILT_IN_EXECVE && fcode != BUILT_IN_ALLOCA && fcode != BUILT_IN_ALLOCA_WITH_ALIGN - && fcode != BUILT_IN_FREE) + && fcode != BUILT_IN_FREE + && fcode != BUILT_IN_CHKP_SET_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_INIT_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_NULL_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_COPY_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_NARROW_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_STORE_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_CHECK_PTR_LBOUNDS + && fcode != BUILT_IN_CHKP_CHECK_PTR_UBOUNDS + && fcode != BUILT_IN_CHKP_CHECK_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_GET_PTR_LBOUND + && fcode != BUILT_IN_CHKP_GET_PTR_UBOUND) return expand_call (exp, target, ignore); /* The built-in function expanders test for target == const0_rtx @@ -6698,6 +6709,51 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, expand_builtin_cilk_pop_frame (exp); return const0_rtx; + case BUILT_IN_CHKP_INIT_PTR_BOUNDS: + case BUILT_IN_CHKP_NULL_PTR_BOUNDS: + case BUILT_IN_CHKP_COPY_PTR_BOUNDS: + return expand_normal (CALL_EXPR_ARG (exp, 0)); + + case BUILT_IN_CHKP_CHECK_PTR_LBOUNDS: + case BUILT_IN_CHKP_CHECK_PTR_UBOUNDS: + case BUILT_IN_CHKP_CHECK_PTR_BOUNDS: + case BUILT_IN_CHKP_SET_PTR_BOUNDS: + case BUILT_IN_CHKP_NARROW_PTR_BOUNDS: + case BUILT_IN_CHKP_STORE_PTR_BOUNDS: + case BUILT_IN_CHKP_GET_PTR_LBOUND: + case BUILT_IN_CHKP_GET_PTR_UBOUND: + /* We allow user CHKP builtins if Pointer Bounds + Checker is off. */ + if (!flag_check_pointer_bounds) + { + if (fcode == BUILT_IN_CHKP_SET_PTR_BOUNDS + || fcode == BUILT_IN_CHKP_NARROW_PTR_BOUNDS) + return expand_normal (CALL_EXPR_ARG (exp, 0)); + else if (fcode == BUILT_IN_CHKP_GET_PTR_LBOUND) + return expand_normal (size_zero_node); + else if (fcode == BUILT_IN_CHKP_GET_PTR_UBOUND) + return expand_normal (size_int (-1)); + else + return const0_rtx; + } + /* FALLTHROUGH */ + + case BUILT_IN_CHKP_BNDMK: + case BUILT_IN_CHKP_BNDSTX: + case BUILT_IN_CHKP_BNDCL: + case BUILT_IN_CHKP_BNDCU: + case BUILT_IN_CHKP_BNDLDX: + case BUILT_IN_CHKP_BNDRET: + case BUILT_IN_CHKP_INTERSECT: + case BUILT_IN_CHKP_ARG_BND: + case BUILT_IN_CHKP_NARROW: + case BUILT_IN_CHKP_EXTRACT_LOWER: + case BUILT_IN_CHKP_EXTRACT_UPPER: + /* Software implementation of pointers checker is NYI. + Target support is required. */ + error ("Your target platform does not support -fcheck-pointers"); + break; + default: /* just do library call, if unknown builtin */ break; } diff --git a/gcc/builtins.def b/gcc/builtins.def index 12c56be5c5b..e2d8849c768 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -176,6 +176,12 @@ along with GCC; see the file COPYING3. If not see DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \ false, false, false, ATTRS, false, flag_enable_cilkplus) +/* Builtin used by the implementation of Pointer Bounds Checker. */ +#undef DEF_CHKP_BUILTIN +#define DEF_CHKP_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ + DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \ + true, true, false, ATTRS, true, true) + /* Define an attribute list for math functions that are normally "impure" because some of them may write into global memory for `errno'. If !flag_errno_math they are instead "const". */ @@ -864,3 +870,6 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST) /* Cilk Plus builtins. */ #include "cilkplus.def" + +/* Pointer Bounds Checker builtins. */ +#include "chkp-builtins.def" diff --git a/gcc/common.opt b/gcc/common.opt index deeb3f20a3b..5c2f56eb8bf 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -874,6 +874,11 @@ fbounds-check Common Report Var(flag_bounds_check) Generate code to check bounds before indexing arrays +fcheck-pointer-bounds +Common Report Var(flag_check_pointer_bounds) +Add Pointer Bounds Checker instrumentation. fchkp-* flags are used to +control instrumentation. Currently available for C, C++ and ObjC. + fbranch-count-reg Common Report Var(flag_branch_on_count_reg) Init(1) Optimization Replace add, compare, branch with branch on count register diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 7623a5e550e..8ca3137ae0f 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -82,6 +82,7 @@ extensions, accepted by GCC in C90 mode and in C++. * x86 specific memory model extensions for transactional memory:: x86 memory models. * Object Size Checking:: Built-in functions for limited buffer overflow checking. +* Pointer Bounds Checker builtins:: Built-in functions for Pointer Bounds Checker. * Cilk Plus Builtins:: Built-in functions for the Cilk Plus language extension. * Other Builtins:: Other built-in functions. * Target Builtins:: Built-in functions specific to particular targets. @@ -7752,6 +7753,176 @@ format string @var{fmt}. If the compiler is able to optimize them to @code{fputc} etc.@: functions, it does, otherwise the checking function is called and the @var{flag} argument passed to it. +@node Pointer Bounds Checker builtins +@section Pointer Bounds Checker Built-in Functions +@findex __builtin___bnd_set_ptr_bounds +@findex __builtin___bnd_narrow_ptr_bounds +@findex __builtin___bnd_copy_ptr_bounds +@findex __builtin___bnd_init_ptr_bounds +@findex __builtin___bnd_null_ptr_bounds +@findex __builtin___bnd_store_ptr_bounds +@findex __builtin___bnd_chk_ptr_lbounds +@findex __builtin___bnd_chk_ptr_ubounds +@findex __builtin___bnd_chk_ptr_bounds +@findex __builtin___bnd_get_ptr_lbound +@findex __builtin___bnd_get_ptr_ubound + +GCC provides a set of built-in functions to control Pointer Bounds Checker +instrumentation. Note that all Pointer Bounds Checker builtins are allowed +to use even if you compile with Pointer Bounds Checker off. But functions +behavior may differ in such case. + +@deftypefn {Built-in Function} void * __builtin___bnd_set_ptr_bounds (const void * @var{q}, size_t @var{size}) + +This built-in function returns a new pointer with the value of @var{q}, and +associate it with the bounds [@var{q}, @var{q}+@var{size}-1]. With Pointer +Bounds Checker off built-in function just returns the first argument. + +@smallexample +extern void *__wrap_malloc (size_t n) +@{ + void *p = (void *)__real_malloc (n); + if (!p) return __builtin___bnd_null_ptr_bounds (p); + return __builtin___bnd_set_ptr_bounds (p, n); +@} +@end smallexample + +@end deftypefn + +@deftypefn {Built-in Function} void * __builtin___bnd_narrow_ptr_bounds (const void * @var{p}, const void * @var{q}, size_t @var{size}) + +This built-in function returns a new pointer with the value of @var{p} +and associate it with the narrowed bounds formed by the intersection +of bounds associated with @var{q} and the [@var{p}, @var{p} + @var{size} - 1]. +With Pointer Bounds Checker off built-in function just returns the first +argument. + +@smallexample +void init_objects (object *objs, size_t size) +@{ + size_t i; + /* Initialize objects one-by-one passing pointers with bounds of an object, + not the full array of objects. */ + for (i = 0; i < size; i++) + init_object (__builtin___bnd_narrow_ptr_bounds (objs + i, objs, sizeof(object))); +@} +@end smallexample + +@end deftypefn + +@deftypefn {Built-in Function} void * __builtin___bnd_copy_ptr_bounds (const void * @var{q}, const void * @var{r}) + +This built-in function returns a new pointer with the value of @var{q}, +and associate it with the bounds already associated with pointer @var{r}. +With Pointer Bounds Checker off built-in function just returns the first +argument. + +@smallexample +/* Here is a way to get pointer to object's field but + still with the full object's bounds. */ +int *field_ptr = __builtin___bnd_copy_ptr_bounds (&objptr->int_filed, objptr); +@end smallexample + +@end deftypefn + +@deftypefn {Built-in Function} void * __builtin___bnd_init_ptr_bounds (const void * @var{q}) + +This built-in function returns a new pointer with the value of @var{q}, and +associate it with INIT (allowing full memory access) bounds. With Pointer +Bounds Checker off built-in function just returns the first argument. + +@end deftypefn + +@deftypefn {Built-in Function} void * __builtin___bnd_null_ptr_bounds (const void * @var{q}) + +This built-in function returns a new pointer with the value of @var{q}, and +associate it with NULL (allowing no memory access) bounds. With Pointer +Bounds Checker off built-in function just returns the first argument. + +@end deftypefn + +@deftypefn {Built-in Function} void __builtin___bnd_store_ptr_bounds (const void ** @var{ptr_addr}, const void * @var{ptr_val}) + +This built-in function stores the bounds associated with pointer @var{ptr_val} +and location @var{ptr_addr} into Bounds Table. This can be useful to propagate +bounds from legacy code without touching the associated pointer's memory when +pointers were copied as integers. With Pointer Bounds Checker off built-in +function call is ignored. + +@end deftypefn + +@deftypefn {Built-in Function} void __builtin___bnd_chk_ptr_lbounds (const void * @var{q}) + +This built-in function checks if the pointer @var{q} is within the lower +bound of its associated bounds. With Pointer Bounds Checker off built-in +function call is ignored. + +@smallexample +extern void *__wrap_memset (void *dst, int c, size_t len) +@{ + if (len > 0) + @{ + __builtin___bnd_chk_ptr_lbounds (dst); + __builtin___bnd_chk_ptr_ubounds ((char *)dst + len - 1); + __real_memset (dst, c, len); + @} + return dst; +@} +@end smallexample + +@end deftypefn + +@deftypefn {Built-in Function} void __builtin___bnd_chk_ptr_ubounds (const void * @var{q}) + +This built-in function checks if the pointer @var{q} is within the upper +bound of its associated bounds. With Pointer Bounds Checker off built-in +function call is ignored. + +@end deftypefn + +@deftypefn {Built-in Function} void __builtin___bnd_chk_ptr_bounds (const void * @var{q}, size_t @var{size}) + +This built-in function checks if [@var{q}, @var{q} + @var{size} - 1] is within +the lower and upper bounds associated with @var{q}. With Pointer Bounds Checker +off built-in function call is ignored. + +@smallexample +extern void *__wrap_memcpy (void *dst, const void *src, size_t n) +@{ + if (n > 0) + @{ + __bnd_chk_ptr_bounds (dst, n); + __bnd_chk_ptr_bounds (src, n); + __real_memcpy (dst, src, n); + @} + return dst; +@} +@end smallexample + +@end deftypefn + +@deftypefn {Built-in Function} const void * __builtin___bnd_get_ptr_lbound (const void * @var{q}) + +This built-in function returns the lower bound (which is a pointer) associated +with the pointer @var{q}. This is at least useful for debugging using printf. +With Pointer Bounds Checker off built-in function returns 0. + +@smallexample +void *lb = __builtin___bnd_get_ptr_lbound (q); +void *ub = __builtin___bnd_get_ptr_ubound (q); +printf ("q = %p lb(q) = %p ub(q) = %p", q, lb, ub); +@end smallexample + +@end deftypefn + +@deftypefn {Built-in Function} const void * __builtin___bnd_get_ptr_ubound (const void * @var{q}) + +This built-in function returns the upper bound (which is a pointer) associated +with the pointer @var{q}. With Pointer Bounds Checker off built-in function +returns -1. + +@end deftypefn + @node Other Builtins @section Other Built-in Functions Provided by GCC @cindex built-in functions diff --git a/gcc/toplev.c b/gcc/toplev.c index 436f7a592f3..f78912e09db 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1282,6 +1282,15 @@ process_options (void) "and -ftree-loop-linear)"); #endif + if (flag_check_pointer_bounds) + { + if (targetm.chkp_bound_mode () == VOIDmode) + error ("-fcheck-pointers is not supported for this target"); + + if (!lang_hooks.chkp_supported) + flag_check_pointer_bounds = 0; + } + /* One region RA really helps to decrease the code size. */ if (flag_ira_region == IRA_REGION_AUTODETECT) flag_ira_region -- 2.30.2