Drop support for -fcheck-pointer-bounds

GCC has removed the -fcheck-pointer bounds option, and the Linux
kernel has also removed support for Intel MPX, so there’s no point
to keeping this debugging option within Emacs.
* src/bytecode.c (BYTE_CODE_THREADED):
* src/lisp.h (DEFINE_LISP_SYMBOL, XSYMBOL, make_lisp_symbol):
Assume __CHKP__ is not defined.
* src/ptr-bounds.h: Remove.  All uses of ptr_bounds_clip,
ptr_bounds_copy, ptr_bounds_init, ptr_bounds_set removed.
This commit is contained in:
Paul Eggert 2020-08-04 11:09:55 -07:00
parent 1308587c25
commit fe2649528b
12 changed files with 31 additions and 168 deletions

View file

@ -58,6 +58,11 @@ shaping, so 'configure' now recommends that combination.
** The ftx font backend driver has been removed.
It was declared obsolete in Emacs 27.1.
---
** Support for building with '-fcheck-pointer-bounds' has been removed.
GCC has withdrawn the '-fcheck-pointer-bounds' option and support for
its implementation has been removed from the Linux kernel.
---
** Emacs no longer supports old OpenBSD systems.
OpenBSD 5.3 and older releases are no longer supported, as they lack

View file

@ -34,7 +34,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "bignum.h"
#include "dispextern.h"
#include "intervals.h"
#include "ptr-bounds.h"
#include "puresize.h"
#include "sheap.h"
#include "sysstdio.h"
@ -1624,8 +1623,7 @@ static struct Lisp_String *string_free_list;
a pointer to the `u.data' member of its sdata structure; the
structure starts at a constant offset in front of that. */
#define SDATA_OF_STRING(S) ((sdata *) ptr_bounds_init ((S)->u.s.data \
- SDATA_DATA_OFFSET))
#define SDATA_OF_STRING(S) ((sdata *) ((S)->u.s.data - SDATA_DATA_OFFSET))
#ifdef GC_CHECK_STRING_OVERRUN
@ -1799,7 +1797,7 @@ allocate_string (void)
/* Every string on a free list should have NULL data pointer. */
s->u.s.data = NULL;
NEXT_FREE_LISP_STRING (s) = string_free_list;
string_free_list = ptr_bounds_clip (s, sizeof *s);
string_free_list = s;
}
}
@ -1908,7 +1906,7 @@ allocate_string_data (struct Lisp_String *s,
MALLOC_UNBLOCK_INPUT;
s->u.s.data = ptr_bounds_clip (SDATA_DATA (data), nbytes + 1);
s->u.s.data = SDATA_DATA (data);
#ifdef GC_CHECK_STRING_BYTES
SDATA_NBYTES (data) = nbytes;
#endif
@ -2036,7 +2034,7 @@ sweep_strings (void)
/* Put the string on the free-list. */
NEXT_FREE_LISP_STRING (s) = string_free_list;
string_free_list = ptr_bounds_clip (s, sizeof *s);
string_free_list = s;
++nfree;
}
}
@ -2044,7 +2042,7 @@ sweep_strings (void)
{
/* S was on the free-list before. Put it there again. */
NEXT_FREE_LISP_STRING (s) = string_free_list;
string_free_list = ptr_bounds_clip (s, sizeof *s);
string_free_list = s;
++nfree;
}
}
@ -2171,8 +2169,7 @@ compact_small_strings (void)
{
eassert (tb != b || to < from);
memmove (to, from, size + GC_STRING_EXTRA);
to->string->u.s.data
= ptr_bounds_clip (SDATA_DATA (to), nbytes + 1);
to->string->u.s.data = SDATA_DATA (to);
}
/* Advance past the sdata we copied to. */
@ -2959,7 +2956,6 @@ Lisp_Object zero_vector;
static void
setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes)
{
v = ptr_bounds_clip (v, nbytes);
eassume (header_size <= nbytes);
ptrdiff_t nwords = (nbytes - header_size) / word_size;
XSETPVECTYPESIZE (v, PVEC_FREE, 0, nwords);
@ -3307,7 +3303,7 @@ allocate_vectorlike (ptrdiff_t len, bool clearit)
MALLOC_UNBLOCK_INPUT;
return ptr_bounds_clip (p, nbytes);
return p;
}
@ -4461,7 +4457,6 @@ live_string_holding (struct mem_node *m, void *p)
must not be on the free-list. */
if (0 <= offset && offset < sizeof b->strings)
{
cp = ptr_bounds_copy (cp, b);
struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0];
if (s->u.s.data)
return s;
@ -4494,7 +4489,6 @@ live_cons_holding (struct mem_node *m, void *p)
&& (b != cons_block
|| offset / sizeof b->conses[0] < cons_block_index))
{
cp = ptr_bounds_copy (cp, b);
struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0];
if (!deadp (s->u.s.car))
return s;
@ -4528,7 +4522,6 @@ live_symbol_holding (struct mem_node *m, void *p)
&& (b != symbol_block
|| offset / sizeof b->symbols[0] < symbol_block_index))
{
cp = ptr_bounds_copy (cp, b);
struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0];
if (!deadp (s->u.s.function))
return s;
@ -5234,7 +5227,7 @@ pure_alloc (size_t size, int type)
pure_bytes_used = pure_bytes_used_lisp + pure_bytes_used_non_lisp;
if (pure_bytes_used <= pure_size)
return ptr_bounds_clip (result, size);
return result;
/* Don't allocate a large amount here,
because it might get mmap'd and then its address
@ -5325,7 +5318,7 @@ find_string_data_in_pure (const char *data, ptrdiff_t nbytes)
/* Check the remaining characters. */
if (memcmp (data, non_lisp_beg + start, nbytes) == 0)
/* Found. */
return ptr_bounds_clip (non_lisp_beg + start, nbytes + 1);
return non_lisp_beg + start;
start += last_char_skip;
}
@ -6049,7 +6042,6 @@ garbage_collect (void)
stack_copy = xrealloc (stack_copy, stack_size);
stack_copy_size = stack_size;
}
stack = ptr_bounds_set (stack, stack_size);
no_sanitize_memcpy (stack_copy, stack, stack_size);
}
}
@ -6885,8 +6877,7 @@ sweep_conses (void)
for (pos = start; pos < stop; pos++)
{
struct Lisp_Cons *acons
= ptr_bounds_copy (&cblk->conses[pos], cblk);
struct Lisp_Cons *acons = &cblk->conses[pos];
if (!XCONS_MARKED_P (acons))
{
this_free++;
@ -6939,7 +6930,7 @@ sweep_floats (void)
int this_free = 0;
for (int i = 0; i < lim; i++)
{
struct Lisp_Float *afloat = ptr_bounds_copy (&fblk->floats[i], fblk);
struct Lisp_Float *afloat = &fblk->floats[i];
if (!XFLOAT_MARKED_P (afloat))
{
this_free++;

View file

@ -24,7 +24,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "character.h"
#include "buffer.h"
#include "keyboard.h"
#include "ptr-bounds.h"
#include "syntax.h"
#include "window.h"
@ -47,7 +46,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
indirect threaded, using GCC's computed goto extension. This code,
as currently implemented, is incompatible with BYTE_CODE_SAFE and
BYTE_CODE_METER. */
#if (defined __GNUC__ && !defined __STRICT_ANSI__ && !defined __CHKP__ \
#if (defined __GNUC__ && !defined __STRICT_ANSI__ \
&& !BYTE_CODE_SAFE && !defined BYTE_CODE_METER)
#define BYTE_CODE_THREADED
#endif
@ -368,14 +367,12 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
USE_SAFE_ALLOCA;
void *alloc;
SAFE_ALLOCA_LISP_EXTRA (alloc, stack_items, bytestr_length);
ptrdiff_t item_bytes = stack_items * word_size;
Lisp_Object *stack_base = ptr_bounds_clip (alloc, item_bytes);
Lisp_Object *stack_base = alloc;
Lisp_Object *top = stack_base;
*top = vector; /* Ensure VECTOR survives GC (Bug#33014). */
Lisp_Object *stack_lim = stack_base + stack_items;
unsigned char *bytestr_data = alloc;
bytestr_data = ptr_bounds_clip (bytestr_data + item_bytes, bytestr_length);
memcpy (bytestr_data, SDATA (bytestr), bytestr_length);
unsigned char const *bytestr_data = memcpy (stack_lim,
SDATA (bytestr), bytestr_length);
unsigned char const *pc = bytestr_data;
ptrdiff_t count = SPECPDL_INDEX ();

View file

@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "lisp.h"
#include "ptr-bounds.h"
#include "character.h"
#include "buffer.h"
#include "keyboard.h"
@ -440,9 +439,6 @@ invoke it (via an `interactive' spec that contains, for instance, an
signed char *varies = (signed char *) (visargs + nargs);
memclear (args, nargs * (2 * word_size + 1));
args = ptr_bounds_clip (args, nargs * sizeof *args);
visargs = ptr_bounds_clip (visargs, nargs * sizeof *visargs);
varies = ptr_bounds_clip (varies, nargs * sizeof *varies);
if (!NILP (enable))
specbind (Qenable_recursive_minibuffers, Qt);

View file

@ -25,7 +25,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <unistd.h>
#include "lisp.h"
#include "ptr-bounds.h"
#include "termchar.h"
/* cm.h must come after dispextern.h on Windows. */
#include "dispextern.h"
@ -4891,12 +4890,6 @@ scrolling (struct frame *frame)
unsigned *new_hash = old_hash + height;
int *draw_cost = (int *) (new_hash + height);
int *old_draw_cost = draw_cost + height;
old_hash = ptr_bounds_clip (old_hash, height * sizeof *old_hash);
new_hash = ptr_bounds_clip (new_hash, height * sizeof *new_hash);
draw_cost = ptr_bounds_clip (draw_cost, height * sizeof *draw_cost);
old_draw_cost = ptr_bounds_clip (old_draw_cost,
height * sizeof *old_draw_cost);
eassert (current_matrix);
/* Compute hash codes of all the lines. Also calculate number of

View file

@ -46,7 +46,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "composite.h"
#include "intervals.h"
#include "ptr-bounds.h"
#include "systime.h"
#include "character.h"
#include "buffer.h"
@ -3131,8 +3130,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
string was not copied into the output.
It is 2 if byte I was not the first byte of its character. */
char *discarded = (char *) &info[nspec_bound];
info = ptr_bounds_clip (info, info_size);
discarded = ptr_bounds_clip (discarded, formatlen);
memset (discarded, 0, formatlen);
/* Try to determine whether the result should be multibyte.

View file

@ -83,7 +83,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "charset.h"
#include "composite.h"
#include "dispextern.h"
#include "ptr-bounds.h"
#include "regex-emacs.h"
#include "sheap.h"
#include "syntax.h"

View file

@ -35,7 +35,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "buffer.h"
/* These help us bind and responding to switch-frame events. */
#include "keyboard.h"
#include "ptr-bounds.h"
#include "frame.h"
#include "blockinput.h"
#include "termchar.h"
@ -5019,8 +5018,6 @@ gui_display_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
USE_SAFE_ALLOCA;
char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
char *class_key = name_key + name_keysize;
name_key = ptr_bounds_clip (name_key, name_keysize);
class_key = ptr_bounds_clip (class_key, class_keysize);
/* Start with emacs.FRAMENAME for the name (the specific one)
and with `Emacs' for the class key (the general one). */
@ -5091,9 +5088,6 @@ x_get_resource_string (const char *attribute, const char *class)
ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
char *class_key = name_key + name_keysize;
name_key = ptr_bounds_clip (name_key, name_keysize);
class_key = ptr_bounds_clip (class_key, class_keysize);
esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
sprintf (class_key, "%s.%s", EMACS_CLASS, class);

View file

@ -23,7 +23,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "lisp.h"
#include "frame.h"
#include "ptr-bounds.h"
#include "window.h"
#include "dispextern.h"
#include "buffer.h"
@ -1607,9 +1606,7 @@ If BITMAP already exists, the existing definition is replaced. */)
fb.dynamic = true;
xfb = xmalloc (sizeof fb + fb.height * BYTES_PER_BITMAP_ROW);
fb.bits = b = ((unsigned short *)
ptr_bounds_clip (xfb + 1, fb.height * BYTES_PER_BITMAP_ROW));
xfb = ptr_bounds_clip (xfb, sizeof *xfb);
fb.bits = b = (unsigned short *) (xfb + 1);
j = 0;
while (j < fb.height)

View file

@ -38,8 +38,6 @@ License along with this library. If not, see <https://www.gnu.org/licenses/>.
#include "lisp.h"
#include "ptr-bounds.h"
#ifdef HAVE_MALLOC_H
# if GNUC_PREREQ (4, 2, 0)
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@ -200,8 +198,7 @@ extern size_t _bytes_free;
/* Internal versions of `malloc', `realloc', and `free'
used when these functions need to call each other.
They are the same but don't call the hooks
and don't bound the resulting pointers. */
They are the same but don't call the hooks. */
extern void *_malloc_internal (size_t);
extern void *_realloc_internal (void *, size_t);
extern void _free_internal (void *);
@ -551,7 +548,7 @@ malloc_initialize_1 (void)
_heapinfo[0].free.size = 0;
_heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
_heapindex = 0;
_heapbase = (char *) ptr_bounds_init (_heapinfo);
_heapbase = (char *) _heapinfo;
_heaplimit = BLOCK (_heapbase + heapsize * sizeof (malloc_info));
register_heapinfo ();
@ -912,8 +909,7 @@ malloc (size_t size)
among multiple threads. We just leave it for compatibility with
glibc malloc (i.e., assignments to gmalloc_hook) for now. */
hook = gmalloc_hook;
void *result = (hook ? hook : _malloc_internal) (size);
return ptr_bounds_clip (result, size);
return (hook ? hook : _malloc_internal) (size);
}
#if !(defined (_LIBC) || defined (HYBRID_MALLOC))
@ -991,7 +987,6 @@ _free_internal_nolock (void *ptr)
if (ptr == NULL)
return;
ptr = ptr_bounds_init (ptr);
PROTECT_MALLOC_STATE (0);
@ -1303,7 +1298,6 @@ _realloc_internal_nolock (void *ptr, size_t size)
else if (ptr == NULL)
return _malloc_internal_nolock (size);
ptr = ptr_bounds_init (ptr);
block = BLOCK (ptr);
PROTECT_MALLOC_STATE (0);
@ -1426,8 +1420,7 @@ realloc (void *ptr, size_t size)
return NULL;
hook = grealloc_hook;
void *result = (hook ? hook : _realloc_internal) (ptr, size);
return ptr_bounds_clip (result, size);
return (hook ? hook : _realloc_internal) (ptr, size);
}
/* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
@ -1601,7 +1594,6 @@ aligned_alloc (size_t alignment, size_t size)
{
l->exact = result;
result = l->aligned = (char *) result + adj;
result = ptr_bounds_clip (result, size);
}
UNLOCK_ALIGNED_BLOCKS ();
if (l == NULL)

View file

@ -893,8 +893,8 @@ verify (GCALIGNED (struct Lisp_Symbol));
convert it to a Lisp_Word. */
#if LISP_WORDS_ARE_POINTERS
/* untagged_ptr is a pointer so that the compiler knows that TAG_PTR
yields a pointer; this can help with gcc -fcheck-pointer-bounds.
It is char * so that adding a tag uses simple machine addition. */
yields a pointer. It is char * so that adding a tag uses simple
machine addition. */
typedef char *untagged_ptr;
typedef uintptr_t Lisp_Word_tag;
#else
@ -922,13 +922,9 @@ typedef EMACS_UINT Lisp_Word_tag;
when using a debugger like GDB, on older platforms where the debug
format does not represent C macros. However, they are unbounded
and would just be asking for trouble if checking pointer bounds. */
#ifdef __CHKP__
# define DEFINE_LISP_SYMBOL(name)
#else
# define DEFINE_LISP_SYMBOL(name) \
DEFINE_GDB_SYMBOL_BEGIN (Lisp_Object, name) \
DEFINE_GDB_SYMBOL_END (LISPSYM_INITIALLY (name))
#endif
#define DEFINE_LISP_SYMBOL(name) \
DEFINE_GDB_SYMBOL_BEGIN (Lisp_Object, name) \
DEFINE_GDB_SYMBOL_END (LISPSYM_INITIALLY (name))
/* The index of the C-defined Lisp symbol SYM.
This can be used in a static initializer. */
@ -1002,30 +998,15 @@ XSYMBOL (Lisp_Object a)
eassert (SYMBOLP (a));
intptr_t i = (intptr_t) XUNTAG (a, Lisp_Symbol, struct Lisp_Symbol);
void *p = (char *) lispsym + i;
#ifdef __CHKP__
/* Bypass pointer checking. Although this could be improved it is
probably not worth the trouble. */
p = __builtin___bnd_set_ptr_bounds (p, sizeof (struct Lisp_Symbol));
#endif
return p;
}
INLINE Lisp_Object
make_lisp_symbol (struct Lisp_Symbol *sym)
{
#ifdef __CHKP__
/* Although '__builtin___bnd_narrow_ptr_bounds (sym, sym, sizeof *sym)'
should be more efficient, it runs afoul of GCC bug 83251
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83251>.
Also, attempting to call __builtin___bnd_chk_ptr_bounds (sym, sizeof *sym)
here seems to trigger a GCC bug, as yet undiagnosed. */
char *addr = __builtin___bnd_set_ptr_bounds (sym, sizeof *sym);
char *symoffset = addr - (intptr_t) lispsym;
#else
/* If !__CHKP__, GCC 7 x86-64 generates faster code if lispsym is
/* GCC 7 x86-64 generates faster code if lispsym is
cast to char * rather than to intptr_t. */
char *symoffset = (char *) ((char *) sym - (char *) lispsym);
#endif
Lisp_Object a = TAG_PTR (Lisp_Symbol, symoffset);
eassert (XSYMBOL (a) == sym);
return a;

View file

@ -1,79 +0,0 @@
/* Pointer bounds checking for GNU Emacs
Copyright 2017-2020 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
/* Pointer bounds checking is a no-op unless running on hardware
supporting Intel MPX (Intel Skylake or better). Also, it requires
GCC 5 and Linux kernel 3.19, or later. Configure with
CFLAGS='-fcheck-pointer-bounds -mmpx', perhaps with
-fchkp-first-field-has-own-bounds thrown in.
Although pointer bounds checking can help during debugging, it is
disabled by default because it hurts performance significantly.
The checking does not detect all pointer errors. For example, a
dumped Emacs might not detect a bounds violation of a pointer that
was created before Emacs was dumped. */
#ifndef PTR_BOUNDS_H
#define PTR_BOUNDS_H
#include <stddef.h>
/* When not checking pointer bounds, the following macros simply
return their first argument. These macros return either void *, or
the same type as their first argument. */
INLINE_HEADER_BEGIN
/* Return a copy of P, with bounds narrowed to [P, P + N). */
#ifdef __CHKP__
INLINE void *
ptr_bounds_clip (void const *p, size_t n)
{
return __builtin___bnd_narrow_ptr_bounds (p, p, n);
}
#else
# define ptr_bounds_clip(p, n) ((void) (size_t) {n}, p)
#endif
/* Return a copy of P, but with the bounds of Q. */
#ifdef __CHKP__
# define ptr_bounds_copy(p, q) __builtin___bnd_copy_ptr_bounds (p, q)
#else
# define ptr_bounds_copy(p, q) ((void) (void const *) {q}, p)
#endif
/* Return a copy of P, but with infinite bounds.
This is a loophole in pointer bounds checking. */
#ifdef __CHKP__
# define ptr_bounds_init(p) __builtin___bnd_init_ptr_bounds (p)
#else
# define ptr_bounds_init(p) (p)
#endif
/* Return a copy of P, but with bounds [P, P + N).
This is a loophole in pointer bounds checking. */
#ifdef __CHKP__
# define ptr_bounds_set(p, n) __builtin___bnd_set_ptr_bounds (p, n)
#else
# define ptr_bounds_set(p, n) ((void) (size_t) {n}, p)
#endif
INLINE_HEADER_END
#endif /* PTR_BOUNDS_H */