aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorVibhav Pant2022-12-20 21:56:02 +0530
committerVibhav Pant2022-12-20 21:56:02 +0530
commite7459fcbde4e468f9dfc74477072c7405b59e03e (patch)
tree524457d1b9f6aa7edb393b540e4123d1fc60942b /src/alloc.c
parent89892db0af4f8a803eb7ff3f5f7880d3126702ff (diff)
parent9fafeb2a66fe1cba8f3ad7662196e36ca0b1eca7 (diff)
downloademacs-e7459fcbde4e468f9dfc74477072c7405b59e03e.tar.gz
emacs-e7459fcbde4e468f9dfc74477072c7405b59e03e.zip
Merge branch 'master' into scratch/comp-static-data
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c289
1 files changed, 278 insertions, 11 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 0a8c1826614..0a4323d1ceb 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -82,6 +82,37 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
82#include <valgrind/memcheck.h> 82#include <valgrind/memcheck.h>
83#endif 83#endif
84 84
85/* AddressSanitizer exposes additional functions for manually marking
86 memory as poisoned/unpoisoned. When ASan is enabled and the needed
87 header is available, memory is poisoned when:
88
89 * An ablock is freed (lisp_align_free), or ablocks are initially
90 allocated (lisp_align_malloc).
91 * An interval_block is initially allocated (make_interval).
92 * A dead INTERVAL is put on the interval free list
93 (sweep_intervals).
94 * A sdata is marked as dead (sweep_strings, pin_string).
95 * An sblock is initially allocated (allocate_string_data).
96 * A string_block is initially allocated (allocate_string).
97 * A dead string is put on string_free_list (sweep_strings).
98 * A float_block is initially allocated (make_float).
99 * A dead float is put on float_free_list.
100 * A cons_block is initially allocated (Fcons).
101 * A dead cons is put on cons_free_list (sweep_cons).
102 * A dead vector is put on vector_free_list (setup_on_free_list),
103 or a new vector block is allocated (allocate_vector_from_block).
104 Accordingly, objects reused from the free list are unpoisoned.
105
106 This feature can be disabled wtih the run-time flag
107 `allow_user_poisoning' set to zero. */
108#if ADDRESS_SANITIZER && defined HAVE_SANITIZER_ASAN_INTERFACE_H \
109 && !defined GC_ASAN_POISON_OBJECTS
110# define GC_ASAN_POISON_OBJECTS 1
111# include <sanitizer/asan_interface.h>
112#else
113# define GC_ASAN_POISON_OBJECTS 0
114#endif
115
85/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects. 116/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects.
86 We turn that on by default when ENABLE_CHECKING is defined; 117 We turn that on by default when ENABLE_CHECKING is defined;
87 define GC_CHECK_MARKED_OBJECTS to zero to disable. */ 118 define GC_CHECK_MARKED_OBJECTS to zero to disable. */
@@ -1164,6 +1195,16 @@ struct ablocks
1164 (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **) (abase))[-1]) 1195 (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **) (abase))[-1])
1165#endif 1196#endif
1166 1197
1198#if GC_ASAN_POISON_OBJECTS
1199# define ASAN_POISON_ABLOCK(b) \
1200 __asan_poison_memory_region (&(b)->x, sizeof ((b)->x))
1201# define ASAN_UNPOISON_ABLOCK(b) \
1202 __asan_unpoison_memory_region (&(b)->x, sizeof ((b)->x))
1203#else
1204# define ASAN_POISON_ABLOCK(b) ((void) 0)
1205# define ASAN_UNPOISON_ABLOCK(b) ((void) 0)
1206#endif
1207
1167/* The list of free ablock. */ 1208/* The list of free ablock. */
1168static struct ablock *free_ablock; 1209static struct ablock *free_ablock;
1169 1210
@@ -1242,6 +1283,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
1242 { 1283 {
1243 abase->blocks[i].abase = abase; 1284 abase->blocks[i].abase = abase;
1244 abase->blocks[i].x.next_free = free_ablock; 1285 abase->blocks[i].x.next_free = free_ablock;
1286 ASAN_POISON_ABLOCK (&abase->blocks[i]);
1245 free_ablock = &abase->blocks[i]; 1287 free_ablock = &abase->blocks[i];
1246 } 1288 }
1247 intptr_t ialigned = aligned; 1289 intptr_t ialigned = aligned;
@@ -1254,6 +1296,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
1254 eassert ((intptr_t) ABLOCKS_BUSY (abase) == aligned); 1296 eassert ((intptr_t) ABLOCKS_BUSY (abase) == aligned);
1255 } 1297 }
1256 1298
1299 ASAN_UNPOISON_ABLOCK (free_ablock);
1257 abase = ABLOCK_ABASE (free_ablock); 1300 abase = ABLOCK_ABASE (free_ablock);
1258 ABLOCKS_BUSY (abase) 1301 ABLOCKS_BUSY (abase)
1259 = (struct ablocks *) (2 + (intptr_t) ABLOCKS_BUSY (abase)); 1302 = (struct ablocks *) (2 + (intptr_t) ABLOCKS_BUSY (abase));
@@ -1285,6 +1328,7 @@ lisp_align_free (void *block)
1285#endif 1328#endif
1286 /* Put on free list. */ 1329 /* Put on free list. */
1287 ablock->x.next_free = free_ablock; 1330 ablock->x.next_free = free_ablock;
1331 ASAN_POISON_ABLOCK (ablock);
1288 free_ablock = ablock; 1332 free_ablock = ablock;
1289 /* Update busy count. */ 1333 /* Update busy count. */
1290 intptr_t busy = (intptr_t) ABLOCKS_BUSY (abase) - 2; 1334 intptr_t busy = (intptr_t) ABLOCKS_BUSY (abase) - 2;
@@ -1297,9 +1341,12 @@ lisp_align_free (void *block)
1297 bool aligned = busy; 1341 bool aligned = busy;
1298 struct ablock **tem = &free_ablock; 1342 struct ablock **tem = &free_ablock;
1299 struct ablock *atop = &abase->blocks[aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1]; 1343 struct ablock *atop = &abase->blocks[aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1];
1300
1301 while (*tem) 1344 while (*tem)
1302 { 1345 {
1346#if GC_ASAN_POISON_OBJECTS
1347 __asan_unpoison_memory_region (&(*tem)->x,
1348 sizeof ((*tem)->x));
1349#endif
1303 if (*tem >= (struct ablock *) abase && *tem < atop) 1350 if (*tem >= (struct ablock *) abase && *tem < atop)
1304 { 1351 {
1305 i++; 1352 i++;
@@ -1428,6 +1475,24 @@ static int interval_block_index = INTERVAL_BLOCK_SIZE;
1428 1475
1429static INTERVAL interval_free_list; 1476static INTERVAL interval_free_list;
1430 1477
1478#if GC_ASAN_POISON_OBJECTS
1479# define ASAN_POISON_INTERVAL_BLOCK(b) \
1480 __asan_poison_memory_region ((b)->intervals, \
1481 sizeof ((b)->intervals))
1482# define ASAN_UNPOISON_INTERVAL_BLOCK(b) \
1483 __asan_unpoison_memory_region ((b)->intervals, \
1484 sizeof ((b)->intervals))
1485# define ASAN_POISON_INTERVAL(i) \
1486 __asan_poison_memory_region ((i), sizeof (*(i)))
1487# define ASAN_UNPOISON_INTERVAL(i) \
1488 __asan_unpoison_memory_region ((i), sizeof (*(i)))
1489#else
1490# define ASAN_POISON_INTERVAL_BLOCK(b) ((void) 0)
1491# define ASAN_UNPOISON_INTERVAL_BLOCK(b) ((void) 0)
1492# define ASAN_POISON_INTERVAL(i) ((void) 0)
1493# define ASAN_UNPOISON_INTERVAL(i) ((void) 0)
1494#endif
1495
1431/* Return a new interval. */ 1496/* Return a new interval. */
1432 1497
1433INTERVAL 1498INTERVAL
@@ -1440,6 +1505,7 @@ make_interval (void)
1440 if (interval_free_list) 1505 if (interval_free_list)
1441 { 1506 {
1442 val = interval_free_list; 1507 val = interval_free_list;
1508 ASAN_UNPOISON_INTERVAL (val);
1443 interval_free_list = INTERVAL_PARENT (interval_free_list); 1509 interval_free_list = INTERVAL_PARENT (interval_free_list);
1444 } 1510 }
1445 else 1511 else
@@ -1450,10 +1516,12 @@ make_interval (void)
1450 = lisp_malloc (sizeof *newi, false, MEM_TYPE_NON_LISP); 1516 = lisp_malloc (sizeof *newi, false, MEM_TYPE_NON_LISP);
1451 1517
1452 newi->next = interval_block; 1518 newi->next = interval_block;
1519 ASAN_POISON_INTERVAL_BLOCK (newi);
1453 interval_block = newi; 1520 interval_block = newi;
1454 interval_block_index = 0; 1521 interval_block_index = 0;
1455 } 1522 }
1456 val = &interval_block->intervals[interval_block_index++]; 1523 val = &interval_block->intervals[interval_block_index++];
1524 ASAN_UNPOISON_INTERVAL (val);
1457 } 1525 }
1458 1526
1459 MALLOC_UNBLOCK_INPUT; 1527 MALLOC_UNBLOCK_INPUT;
@@ -1694,6 +1762,41 @@ init_strings (void)
1694 staticpro (&empty_multibyte_string); 1762 staticpro (&empty_multibyte_string);
1695} 1763}
1696 1764
1765#if GC_ASAN_POISON_OBJECTS
1766/* Prepare s for denoting a free sdata struct, i.e, poison all bytes
1767 in the flexible array member, except the first SDATA_OFFSET bytes.
1768 This is only effective for strings of size n where n > sdata_size(n).
1769 */
1770# define ASAN_PREPARE_DEAD_SDATA(s, size) \
1771 do { \
1772 __asan_poison_memory_region ((s), sdata_size ((size))); \
1773 __asan_unpoison_memory_region (&(((s))->string), \
1774 sizeof (struct Lisp_String *)); \
1775 __asan_unpoison_memory_region (&SDATA_NBYTES ((s)), \
1776 sizeof (SDATA_NBYTES ((s)))); \
1777 } while (false)
1778/* Prepare s for storing string data for NBYTES bytes. */
1779# define ASAN_PREPARE_LIVE_SDATA(s, nbytes) \
1780 __asan_unpoison_memory_region ((s), sdata_size ((nbytes)))
1781# define ASAN_POISON_SBLOCK_DATA(b, size) \
1782 __asan_poison_memory_region ((b)->data, (size))
1783# define ASAN_POISON_STRING_BLOCK(b) \
1784 __asan_poison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
1785# define ASAN_UNPOISON_STRING_BLOCK(b) \
1786 __asan_unpoison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
1787# define ASAN_POISON_STRING(s) \
1788 __asan_poison_memory_region ((s), sizeof (*(s)))
1789# define ASAN_UNPOISON_STRING(s) \
1790 __asan_unpoison_memory_region ((s), sizeof (*(s)))
1791#else
1792# define ASAN_PREPARE_DEAD_SDATA(s, size) ((void) 0)
1793# define ASAN_PREPARE_LIVE_SDATA(s, nbytes) ((void) 0)
1794# define ASAN_POISON_SBLOCK_DATA(b, size) ((void) 0)
1795# define ASAN_POISON_STRING_BLOCK(b) ((void) 0)
1796# define ASAN_UNPOISON_STRING_BLOCK(b) ((void) 0)
1797# define ASAN_POISON_STRING(s) ((void) 0)
1798# define ASAN_UNPOISON_STRING(s) ((void) 0)
1799#endif
1697 1800
1698#ifdef GC_CHECK_STRING_BYTES 1801#ifdef GC_CHECK_STRING_BYTES
1699 1802
@@ -1812,12 +1915,14 @@ allocate_string (void)
1812 NEXT_FREE_LISP_STRING (s) = string_free_list; 1915 NEXT_FREE_LISP_STRING (s) = string_free_list;
1813 string_free_list = s; 1916 string_free_list = s;
1814 } 1917 }
1918 ASAN_POISON_STRING_BLOCK (b);
1815 } 1919 }
1816 1920
1817 check_string_free_list (); 1921 check_string_free_list ();
1818 1922
1819 /* Pop a Lisp_String off the free-list. */ 1923 /* Pop a Lisp_String off the free-list. */
1820 s = string_free_list; 1924 s = string_free_list;
1925 ASAN_UNPOISON_STRING (s);
1821 string_free_list = NEXT_FREE_LISP_STRING (s); 1926 string_free_list = NEXT_FREE_LISP_STRING (s);
1822 1927
1823 MALLOC_UNBLOCK_INPUT; 1928 MALLOC_UNBLOCK_INPUT;
@@ -1877,6 +1982,7 @@ allocate_string_data (struct Lisp_String *s,
1877#endif 1982#endif
1878 1983
1879 b = lisp_malloc (size + GC_STRING_EXTRA, clearit, MEM_TYPE_NON_LISP); 1984 b = lisp_malloc (size + GC_STRING_EXTRA, clearit, MEM_TYPE_NON_LISP);
1985 ASAN_POISON_SBLOCK_DATA (b, size);
1880 1986
1881#ifdef DOUG_LEA_MALLOC 1987#ifdef DOUG_LEA_MALLOC
1882 if (!mmap_lisp_allowed_p ()) 1988 if (!mmap_lisp_allowed_p ())
@@ -1898,6 +2004,8 @@ allocate_string_data (struct Lisp_String *s,
1898 { 2004 {
1899 /* Not enough room in the current sblock. */ 2005 /* Not enough room in the current sblock. */
1900 b = lisp_malloc (SBLOCK_SIZE, false, MEM_TYPE_NON_LISP); 2006 b = lisp_malloc (SBLOCK_SIZE, false, MEM_TYPE_NON_LISP);
2007 ASAN_POISON_SBLOCK_DATA (b, SBLOCK_SIZE);
2008
1901 data = b->data; 2009 data = b->data;
1902 b->next = NULL; 2010 b->next = NULL;
1903 b->next_free = data; 2011 b->next_free = data;
@@ -1910,10 +2018,19 @@ allocate_string_data (struct Lisp_String *s,
1910 } 2018 }
1911 2019
1912 data = b->next_free; 2020 data = b->next_free;
2021
1913 if (clearit) 2022 if (clearit)
1914 memset (SDATA_DATA (data), 0, nbytes); 2023 {
2024#if GC_ASAN_POISON_OBJECTS
2025 /* We are accessing SDATA_DATA (data) before it gets
2026 * normally unpoisoned, so do it manually. */
2027 __asan_unpoison_memory_region (SDATA_DATA (data), nbytes);
2028#endif
2029 memset (SDATA_DATA (data), 0, nbytes);
2030 }
1915 } 2031 }
1916 2032
2033 ASAN_PREPARE_LIVE_SDATA (data, nbytes);
1917 data->string = s; 2034 data->string = s;
1918 b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA); 2035 b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA);
1919 eassert ((uintptr_t) b->next_free % alignof (sdata) == 0); 2036 eassert ((uintptr_t) b->next_free % alignof (sdata) == 0);
@@ -2005,12 +2122,16 @@ sweep_strings (void)
2005 int i, nfree = 0; 2122 int i, nfree = 0;
2006 struct Lisp_String *free_list_before = string_free_list; 2123 struct Lisp_String *free_list_before = string_free_list;
2007 2124
2125 ASAN_UNPOISON_STRING_BLOCK (b);
2126
2008 next = b->next; 2127 next = b->next;
2009 2128
2010 for (i = 0; i < STRING_BLOCK_SIZE; ++i) 2129 for (i = 0; i < STRING_BLOCK_SIZE; ++i)
2011 { 2130 {
2012 struct Lisp_String *s = b->strings + i; 2131 struct Lisp_String *s = b->strings + i;
2013 2132
2133 ASAN_UNPOISON_STRING (s);
2134
2014 if (s->u.s.data) 2135 if (s->u.s.data)
2015 { 2136 {
2016 /* String was not on free-list before. */ 2137 /* String was not on free-list before. */
@@ -2047,6 +2168,8 @@ sweep_strings (void)
2047 2168
2048 /* Put the string on the free-list. */ 2169 /* Put the string on the free-list. */
2049 NEXT_FREE_LISP_STRING (s) = string_free_list; 2170 NEXT_FREE_LISP_STRING (s) = string_free_list;
2171 ASAN_POISON_STRING (s);
2172 ASAN_PREPARE_DEAD_SDATA (data, SDATA_NBYTES (data));
2050 string_free_list = s; 2173 string_free_list = s;
2051 ++nfree; 2174 ++nfree;
2052 } 2175 }
@@ -2055,6 +2178,8 @@ sweep_strings (void)
2055 { 2178 {
2056 /* S was on the free-list before. Put it there again. */ 2179 /* S was on the free-list before. Put it there again. */
2057 NEXT_FREE_LISP_STRING (s) = string_free_list; 2180 NEXT_FREE_LISP_STRING (s) = string_free_list;
2181 ASAN_POISON_STRING (s);
2182
2058 string_free_list = s; 2183 string_free_list = s;
2059 ++nfree; 2184 ++nfree;
2060 } 2185 }
@@ -2181,6 +2306,7 @@ compact_small_strings (void)
2181 if (from != to) 2306 if (from != to)
2182 { 2307 {
2183 eassert (tb != b || to < from); 2308 eassert (tb != b || to < from);
2309 ASAN_PREPARE_LIVE_SDATA (to, nbytes);
2184 memmove (to, from, size + GC_STRING_EXTRA); 2310 memmove (to, from, size + GC_STRING_EXTRA);
2185 to->string->u.s.data = SDATA_DATA (to); 2311 to->string->u.s.data = SDATA_DATA (to);
2186 } 2312 }
@@ -2537,6 +2663,7 @@ pin_string (Lisp_Object string)
2537 memcpy (s->u.s.data, data, size); 2663 memcpy (s->u.s.data, data, size);
2538 old_sdata->string = NULL; 2664 old_sdata->string = NULL;
2539 SDATA_NBYTES (old_sdata) = size; 2665 SDATA_NBYTES (old_sdata) = size;
2666 ASAN_PREPARE_DEAD_SDATA (old_sdata, size);
2540 } 2667 }
2541 if (s->u.s.size_byte != -3) 2668 if (s->u.s.size_byte != -3)
2542 s->u.s.size_byte = -3; 2669 s->u.s.size_byte = -3;
@@ -2601,6 +2728,24 @@ struct float_block
2601#define XFLOAT_UNMARK(fptr) \ 2728#define XFLOAT_UNMARK(fptr) \
2602 UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr))) 2729 UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
2603 2730
2731#if GC_ASAN_POISON_OBJECTS
2732# define ASAN_POISON_FLOAT_BLOCK(fblk) \
2733 __asan_poison_memory_region ((fblk)->floats, \
2734 sizeof ((fblk)->floats))
2735# define ASAN_UNPOISON_FLOAT_BLOCK(fblk) \
2736 __asan_unpoison_memory_region ((fblk)->floats, \
2737 sizeof ((fblk)->floats))
2738# define ASAN_POISON_FLOAT(p) \
2739 __asan_poison_memory_region ((p), sizeof (struct Lisp_Float))
2740# define ASAN_UNPOISON_FLOAT(p) \
2741 __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Float))
2742#else
2743# define ASAN_POISON_FLOAT_BLOCK(fblk) ((void) 0)
2744# define ASAN_UNPOISON_FLOAT_BLOCK(fblk) ((void) 0)
2745# define ASAN_POISON_FLOAT(p) ((void) 0)
2746# define ASAN_UNPOISON_FLOAT(p) ((void) 0)
2747#endif
2748
2604/* Current float_block. */ 2749/* Current float_block. */
2605 2750
2606static struct float_block *float_block; 2751static struct float_block *float_block;
@@ -2625,6 +2770,7 @@ make_float (double float_value)
2625 if (float_free_list) 2770 if (float_free_list)
2626 { 2771 {
2627 XSETFLOAT (val, float_free_list); 2772 XSETFLOAT (val, float_free_list);
2773 ASAN_UNPOISON_FLOAT (float_free_list);
2628 float_free_list = float_free_list->u.chain; 2774 float_free_list = float_free_list->u.chain;
2629 } 2775 }
2630 else 2776 else
@@ -2635,9 +2781,11 @@ make_float (double float_value)
2635 = lisp_align_malloc (sizeof *new, MEM_TYPE_FLOAT); 2781 = lisp_align_malloc (sizeof *new, MEM_TYPE_FLOAT);
2636 new->next = float_block; 2782 new->next = float_block;
2637 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); 2783 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
2784 ASAN_POISON_FLOAT_BLOCK (new);
2638 float_block = new; 2785 float_block = new;
2639 float_block_index = 0; 2786 float_block_index = 0;
2640 } 2787 }
2788 ASAN_UNPOISON_FLOAT (&float_block->floats[float_block_index]);
2641 XSETFLOAT (val, &float_block->floats[float_block_index]); 2789 XSETFLOAT (val, &float_block->floats[float_block_index]);
2642 float_block_index++; 2790 float_block_index++;
2643 } 2791 }
@@ -2715,6 +2863,19 @@ static int cons_block_index = CONS_BLOCK_SIZE;
2715 2863
2716static struct Lisp_Cons *cons_free_list; 2864static struct Lisp_Cons *cons_free_list;
2717 2865
2866#if GC_ASAN_POISON_OBJECTS
2867# define ASAN_POISON_CONS_BLOCK(b) \
2868 __asan_poison_memory_region ((b)->conses, sizeof ((b)->conses))
2869# define ASAN_POISON_CONS(p) \
2870 __asan_poison_memory_region ((p), sizeof (struct Lisp_Cons))
2871# define ASAN_UNPOISON_CONS(p) \
2872 __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Cons))
2873#else
2874# define ASAN_POISON_CONS_BLOCK(b) ((void) 0)
2875# define ASAN_POISON_CONS(p) ((void) 0)
2876# define ASAN_UNPOISON_CONS(p) ((void) 0)
2877#endif
2878
2718/* Explicitly free a cons cell by putting it on the free-list. */ 2879/* Explicitly free a cons cell by putting it on the free-list. */
2719 2880
2720void 2881void
@@ -2725,6 +2886,7 @@ free_cons (struct Lisp_Cons *ptr)
2725 cons_free_list = ptr; 2886 cons_free_list = ptr;
2726 ptrdiff_t nbytes = sizeof *ptr; 2887 ptrdiff_t nbytes = sizeof *ptr;
2727 tally_consing (-nbytes); 2888 tally_consing (-nbytes);
2889 ASAN_POISON_CONS (ptr);
2728} 2890}
2729 2891
2730DEFUN ("cons", Fcons, Scons, 2, 2, 0, 2892DEFUN ("cons", Fcons, Scons, 2, 2, 0,
@@ -2737,6 +2899,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
2737 2899
2738 if (cons_free_list) 2900 if (cons_free_list)
2739 { 2901 {
2902 ASAN_UNPOISON_CONS (cons_free_list);
2740 XSETCONS (val, cons_free_list); 2903 XSETCONS (val, cons_free_list);
2741 cons_free_list = cons_free_list->u.s.u.chain; 2904 cons_free_list = cons_free_list->u.s.u.chain;
2742 } 2905 }
@@ -2747,10 +2910,12 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
2747 struct cons_block *new 2910 struct cons_block *new
2748 = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS); 2911 = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS);
2749 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); 2912 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
2913 ASAN_POISON_CONS_BLOCK (new);
2750 new->next = cons_block; 2914 new->next = cons_block;
2751 cons_block = new; 2915 cons_block = new;
2752 cons_block_index = 0; 2916 cons_block_index = 0;
2753 } 2917 }
2918 ASAN_UNPOISON_CONS (&cons_block->conses[cons_block_index]);
2754 XSETCONS (val, &cons_block->conses[cons_block_index]); 2919 XSETCONS (val, &cons_block->conses[cons_block_index]);
2755 cons_block_index++; 2920 cons_block_index++;
2756 } 2921 }
@@ -3005,6 +3170,19 @@ static struct large_vector *large_vectors;
3005 3170
3006Lisp_Object zero_vector; 3171Lisp_Object zero_vector;
3007 3172
3173#if GC_ASAN_POISON_OBJECTS
3174# define ASAN_POISON_VECTOR_CONTENTS(v, bytes) \
3175 __asan_poison_memory_region ((v)->contents, (bytes))
3176# define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) \
3177 __asan_unpoison_memory_region ((v)->contents, (bytes))
3178# define ASAN_UNPOISON_VECTOR_BLOCK(b) \
3179 __asan_unpoison_memory_region ((b)->data, sizeof ((b)->data))
3180#else
3181# define ASAN_POISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
3182# define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
3183# define ASAN_UNPOISON_VECTOR_BLOCK(b) ((void) 0)
3184#endif
3185
3008/* Common shortcut to setup vector on a free list. */ 3186/* Common shortcut to setup vector on a free list. */
3009 3187
3010static void 3188static void
@@ -3017,6 +3195,7 @@ setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes)
3017 ptrdiff_t vindex = VINDEX (nbytes); 3195 ptrdiff_t vindex = VINDEX (nbytes);
3018 eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX); 3196 eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX);
3019 set_next_vector (v, vector_free_lists[vindex]); 3197 set_next_vector (v, vector_free_lists[vindex]);
3198 ASAN_POISON_VECTOR_CONTENTS (v, nbytes - header_size);
3020 vector_free_lists[vindex] = v; 3199 vector_free_lists[vindex] = v;
3021} 3200}
3022 3201
@@ -3064,6 +3243,7 @@ allocate_vector_from_block (ptrdiff_t nbytes)
3064 if (vector_free_lists[index]) 3243 if (vector_free_lists[index])
3065 { 3244 {
3066 vector = vector_free_lists[index]; 3245 vector = vector_free_lists[index];
3246 ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size);
3067 vector_free_lists[index] = next_vector (vector); 3247 vector_free_lists[index] = next_vector (vector);
3068 return vector; 3248 return vector;
3069 } 3249 }
@@ -3077,12 +3257,18 @@ allocate_vector_from_block (ptrdiff_t nbytes)
3077 { 3257 {
3078 /* This vector is larger than requested. */ 3258 /* This vector is larger than requested. */
3079 vector = vector_free_lists[index]; 3259 vector = vector_free_lists[index];
3260 ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size);
3080 vector_free_lists[index] = next_vector (vector); 3261 vector_free_lists[index] = next_vector (vector);
3081 3262
3082 /* Excess bytes are used for the smaller vector, 3263 /* Excess bytes are used for the smaller vector,
3083 which should be set on an appropriate free list. */ 3264 which should be set on an appropriate free list. */
3084 restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes; 3265 restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes;
3085 eassert (restbytes % roundup_size == 0); 3266 eassert (restbytes % roundup_size == 0);
3267#if GC_ASAN_POISON_OBJECTS
3268 /* Ensure that accessing excess bytes does not trigger ASan. */
3269 __asan_unpoison_memory_region (ADVANCE (vector, nbytes),
3270 restbytes);
3271#endif
3086 setup_on_free_list (ADVANCE (vector, nbytes), restbytes); 3272 setup_on_free_list (ADVANCE (vector, nbytes), restbytes);
3087 return vector; 3273 return vector;
3088 } 3274 }
@@ -3258,6 +3444,7 @@ sweep_vectors (void)
3258 for (vector = (struct Lisp_Vector *) block->data; 3444 for (vector = (struct Lisp_Vector *) block->data;
3259 VECTOR_IN_BLOCK (vector, block); vector = next) 3445 VECTOR_IN_BLOCK (vector, block); vector = next)
3260 { 3446 {
3447 ASAN_UNPOISON_VECTOR_BLOCK (block);
3261 if (XVECTOR_MARKED_P (vector)) 3448 if (XVECTOR_MARKED_P (vector))
3262 { 3449 {
3263 XUNMARK_VECTOR (vector); 3450 XUNMARK_VECTOR (vector);
@@ -3633,6 +3820,23 @@ struct symbol_block
3633 struct symbol_block *next; 3820 struct symbol_block *next;
3634}; 3821};
3635 3822
3823#if GC_ASAN_POISON_OBJECTS
3824# define ASAN_POISON_SYMBOL_BLOCK(s) \
3825 __asan_poison_memory_region ((s)->symbols, sizeof ((s)->symbols))
3826# define ASAN_UNPOISON_SYMBOL_BLOCK(s) \
3827 __asan_unpoison_memory_region ((s)->symbols, sizeof ((s)->symbols))
3828# define ASAN_POISON_SYMBOL(sym) \
3829 __asan_poison_memory_region ((sym), sizeof (*(sym)))
3830# define ASAN_UNPOISON_SYMBOL(sym) \
3831 __asan_unpoison_memory_region ((sym), sizeof (*(sym)))
3832
3833#else
3834# define ASAN_POISON_SYMBOL_BLOCK(s) ((void) 0)
3835# define ASAN_UNPOISON_SYMBOL_BLOCK(s) ((void) 0)
3836# define ASAN_POISON_SYMBOL(sym) ((void) 0)
3837# define ASAN_UNPOISON_SYMBOL(sym) ((void) 0)
3838#endif
3839
3636/* Current symbol block and index of first unused Lisp_Symbol 3840/* Current symbol block and index of first unused Lisp_Symbol
3637 structure in it. */ 3841 structure in it. */
3638 3842
@@ -3686,6 +3890,7 @@ Its value is void, and its function definition and property list are nil. */)
3686 3890
3687 if (symbol_free_list) 3891 if (symbol_free_list)
3688 { 3892 {
3893 ASAN_UNPOISON_SYMBOL (symbol_free_list);
3689 XSETSYMBOL (val, symbol_free_list); 3894 XSETSYMBOL (val, symbol_free_list);
3690 symbol_free_list = symbol_free_list->u.s.next; 3895 symbol_free_list = symbol_free_list->u.s.next;
3691 } 3896 }
@@ -3695,10 +3900,13 @@ Its value is void, and its function definition and property list are nil. */)
3695 { 3900 {
3696 struct symbol_block *new 3901 struct symbol_block *new
3697 = lisp_malloc (sizeof *new, false, MEM_TYPE_SYMBOL); 3902 = lisp_malloc (sizeof *new, false, MEM_TYPE_SYMBOL);
3903 ASAN_POISON_SYMBOL_BLOCK (new);
3698 new->next = symbol_block; 3904 new->next = symbol_block;
3699 symbol_block = new; 3905 symbol_block = new;
3700 symbol_block_index = 0; 3906 symbol_block_index = 0;
3701 } 3907 }
3908
3909 ASAN_UNPOISON_SYMBOL (&symbol_block->symbols[symbol_block_index]);
3702 XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]); 3910 XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]);
3703 symbol_block_index++; 3911 symbol_block_index++;
3704 } 3912 }
@@ -4624,6 +4832,11 @@ static struct Lisp_String *
4624live_string_holding (struct mem_node *m, void *p) 4832live_string_holding (struct mem_node *m, void *p)
4625{ 4833{
4626 eassert (m->type == MEM_TYPE_STRING); 4834 eassert (m->type == MEM_TYPE_STRING);
4835#if GC_ASAN_POISON_OBJECTS
4836 if (__asan_address_is_poisoned (p))
4837 return NULL;
4838#endif
4839
4627 struct string_block *b = m->start; 4840 struct string_block *b = m->start;
4628 char *cp = p; 4841 char *cp = p;
4629 ptrdiff_t offset = cp - (char *) &b->strings[0]; 4842 ptrdiff_t offset = cp - (char *) &b->strings[0];
@@ -4640,6 +4853,10 @@ live_string_holding (struct mem_node *m, void *p)
4640 || off == offsetof (struct Lisp_String, u.s.data)) 4853 || off == offsetof (struct Lisp_String, u.s.data))
4641 { 4854 {
4642 struct Lisp_String *s = p = cp -= off; 4855 struct Lisp_String *s = p = cp -= off;
4856#if GC_ASAN_POISON_OBJECTS
4857 if (__asan_region_is_poisoned (s, sizeof (*s)))
4858 return NULL;
4859#endif
4643 if (s->u.s.data) 4860 if (s->u.s.data)
4644 return s; 4861 return s;
4645 } 4862 }
@@ -4661,6 +4878,11 @@ static struct Lisp_Cons *
4661live_cons_holding (struct mem_node *m, void *p) 4878live_cons_holding (struct mem_node *m, void *p)
4662{ 4879{
4663 eassert (m->type == MEM_TYPE_CONS); 4880 eassert (m->type == MEM_TYPE_CONS);
4881#if GC_ASAN_POISON_OBJECTS
4882 if (__asan_address_is_poisoned (p))
4883 return NULL;
4884#endif
4885
4664 struct cons_block *b = m->start; 4886 struct cons_block *b = m->start;
4665 char *cp = p; 4887 char *cp = p;
4666 ptrdiff_t offset = cp - (char *) &b->conses[0]; 4888 ptrdiff_t offset = cp - (char *) &b->conses[0];
@@ -4678,6 +4900,10 @@ live_cons_holding (struct mem_node *m, void *p)
4678 || off == offsetof (struct Lisp_Cons, u.s.u.cdr)) 4900 || off == offsetof (struct Lisp_Cons, u.s.u.cdr))
4679 { 4901 {
4680 struct Lisp_Cons *s = p = cp -= off; 4902 struct Lisp_Cons *s = p = cp -= off;
4903#if GC_ASAN_POISON_OBJECTS
4904 if (__asan_region_is_poisoned (s, sizeof (*s)))
4905 return NULL;
4906#endif
4681 if (!deadp (s->u.s.car)) 4907 if (!deadp (s->u.s.car))
4682 return s; 4908 return s;
4683 } 4909 }
@@ -4700,6 +4926,10 @@ static struct Lisp_Symbol *
4700live_symbol_holding (struct mem_node *m, void *p) 4926live_symbol_holding (struct mem_node *m, void *p)
4701{ 4927{
4702 eassert (m->type == MEM_TYPE_SYMBOL); 4928 eassert (m->type == MEM_TYPE_SYMBOL);
4929#if GC_ASAN_POISON_OBJECTS
4930 if (__asan_address_is_poisoned (p))
4931 return NULL;
4932#endif
4703 struct symbol_block *b = m->start; 4933 struct symbol_block *b = m->start;
4704 char *cp = p; 4934 char *cp = p;
4705 ptrdiff_t offset = cp - (char *) &b->symbols[0]; 4935 ptrdiff_t offset = cp - (char *) &b->symbols[0];
@@ -4725,6 +4955,10 @@ live_symbol_holding (struct mem_node *m, void *p)
4725 || off == offsetof (struct Lisp_Symbol, u.s.next)) 4955 || off == offsetof (struct Lisp_Symbol, u.s.next))
4726 { 4956 {
4727 struct Lisp_Symbol *s = p = cp -= off; 4957 struct Lisp_Symbol *s = p = cp -= off;
4958#if GC_ASAN_POISON_OBJECTS
4959 if (__asan_region_is_poisoned (s, sizeof (*s)))
4960 return NULL;
4961#endif
4728 if (!deadp (s->u.s.function)) 4962 if (!deadp (s->u.s.function))
4729 return s; 4963 return s;
4730 } 4964 }
@@ -4747,6 +4981,11 @@ static struct Lisp_Float *
4747live_float_holding (struct mem_node *m, void *p) 4981live_float_holding (struct mem_node *m, void *p)
4748{ 4982{
4749 eassert (m->type == MEM_TYPE_FLOAT); 4983 eassert (m->type == MEM_TYPE_FLOAT);
4984#if GC_ASAN_POISON_OBJECTS
4985 if (__asan_address_is_poisoned (p))
4986 return NULL;
4987#endif
4988
4750 struct float_block *b = m->start; 4989 struct float_block *b = m->start;
4751 char *cp = p; 4990 char *cp = p;
4752 ptrdiff_t offset = cp - (char *) &b->floats[0]; 4991 ptrdiff_t offset = cp - (char *) &b->floats[0];
@@ -4761,8 +5000,12 @@ live_float_holding (struct mem_node *m, void *p)
4761 && (b != float_block 5000 && (b != float_block
4762 || offset / sizeof b->floats[0] < float_block_index)) 5001 || offset / sizeof b->floats[0] < float_block_index))
4763 { 5002 {
4764 p = cp - off; 5003 struct Lisp_Float *f = (struct Lisp_Float *) (cp - off);
4765 return p; 5004#if GC_ASAN_POISON_OBJECTS
5005 if (__asan_region_is_poisoned (f, sizeof (*f)))
5006 return NULL;
5007#endif
5008 return f;
4766 } 5009 }
4767 } 5010 }
4768 return NULL; 5011 return NULL;
@@ -5338,7 +5581,8 @@ valid_lisp_object_p (Lisp_Object obj)
5338 if (valid <= 0) 5581 if (valid <= 0)
5339 return valid; 5582 return valid;
5340 5583
5341 if (SUBRP (obj)) 5584 /* Strings and conses produced by AUTO_STRING etc. all get here. */
5585 if (SUBRP (obj) || STRINGP (obj) || CONSP (obj))
5342 return 1; 5586 return 1;
5343 5587
5344#ifdef HAVE_STATIC_LISP_GLOBALS 5588#ifdef HAVE_STATIC_LISP_GLOBALS
@@ -6287,6 +6531,7 @@ garbage_collect (void)
6287 6531
6288#ifdef HAVE_X_WINDOWS 6532#ifdef HAVE_X_WINDOWS
6289 mark_xterm (); 6533 mark_xterm ();
6534 mark_xselect ();
6290#endif 6535#endif
6291 6536
6292#ifdef HAVE_NS 6537#ifdef HAVE_NS
@@ -6647,7 +6892,7 @@ mark_buffer (struct buffer *buffer)
6647 if (!BUFFER_LIVE_P (buffer)) 6892 if (!BUFFER_LIVE_P (buffer))
6648 mark_object (BVAR (buffer, undo_list)); 6893 mark_object (BVAR (buffer, undo_list));
6649 6894
6650 if (buffer->overlays) 6895 if (!itree_empty_p (buffer->overlays))
6651 mark_overlays (buffer->overlays->root); 6896 mark_overlays (buffer->overlays->root);
6652 6897
6653 /* If this is an indirect buffer, mark its base buffer. */ 6898 /* If this is an indirect buffer, mark its base buffer. */
@@ -7292,11 +7537,13 @@ sweep_conses (void)
7292 struct Lisp_Cons *acons = &cblk->conses[pos]; 7537 struct Lisp_Cons *acons = &cblk->conses[pos];
7293 if (!XCONS_MARKED_P (acons)) 7538 if (!XCONS_MARKED_P (acons))
7294 { 7539 {
7540 ASAN_UNPOISON_CONS (&cblk->conses[pos]);
7295 this_free++; 7541 this_free++;
7296 cblk->conses[pos].u.s.u.chain = cons_free_list; 7542 cblk->conses[pos].u.s.u.chain = cons_free_list;
7297 cons_free_list = &cblk->conses[pos]; 7543 cons_free_list = &cblk->conses[pos];
7298 cons_free_list->u.s.car = dead_object (); 7544 cons_free_list->u.s.car = dead_object ();
7299 } 7545 ASAN_POISON_CONS (&cblk->conses[pos]);
7546 }
7300 else 7547 else
7301 { 7548 {
7302 num_used++; 7549 num_used++;
@@ -7314,6 +7561,7 @@ sweep_conses (void)
7314 { 7561 {
7315 *cprev = cblk->next; 7562 *cprev = cblk->next;
7316 /* Unhook from the free list. */ 7563 /* Unhook from the free list. */
7564 ASAN_UNPOISON_CONS (&cblk->conses[0]);
7317 cons_free_list = cblk->conses[0].u.s.u.chain; 7565 cons_free_list = cblk->conses[0].u.s.u.chain;
7318 lisp_align_free (cblk); 7566 lisp_align_free (cblk);
7319 } 7567 }
@@ -7340,6 +7588,7 @@ sweep_floats (void)
7340 for (struct float_block *fblk; (fblk = *fprev); ) 7588 for (struct float_block *fblk; (fblk = *fprev); )
7341 { 7589 {
7342 int this_free = 0; 7590 int this_free = 0;
7591 ASAN_UNPOISON_FLOAT_BLOCK (fblk);
7343 for (int i = 0; i < lim; i++) 7592 for (int i = 0; i < lim; i++)
7344 { 7593 {
7345 struct Lisp_Float *afloat = &fblk->floats[i]; 7594 struct Lisp_Float *afloat = &fblk->floats[i];
@@ -7347,6 +7596,7 @@ sweep_floats (void)
7347 { 7596 {
7348 this_free++; 7597 this_free++;
7349 fblk->floats[i].u.chain = float_free_list; 7598 fblk->floats[i].u.chain = float_free_list;
7599 ASAN_POISON_FLOAT (&fblk->floats[i]);
7350 float_free_list = &fblk->floats[i]; 7600 float_free_list = &fblk->floats[i];
7351 } 7601 }
7352 else 7602 else
@@ -7363,7 +7613,8 @@ sweep_floats (void)
7363 { 7613 {
7364 *fprev = fblk->next; 7614 *fprev = fblk->next;
7365 /* Unhook from the free list. */ 7615 /* Unhook from the free list. */
7366 float_free_list = fblk->floats[0].u.chain; 7616 ASAN_UNPOISON_FLOAT (&fblk->floats[0]);
7617 float_free_list = fblk->floats[0].u.chain;
7367 lisp_align_free (fblk); 7618 lisp_align_free (fblk);
7368 } 7619 }
7369 else 7620 else
@@ -7389,13 +7640,14 @@ sweep_intervals (void)
7389 for (struct interval_block *iblk; (iblk = *iprev); ) 7640 for (struct interval_block *iblk; (iblk = *iprev); )
7390 { 7641 {
7391 int this_free = 0; 7642 int this_free = 0;
7392 7643 ASAN_UNPOISON_INTERVAL_BLOCK (iblk);
7393 for (int i = 0; i < lim; i++) 7644 for (int i = 0; i < lim; i++)
7394 { 7645 {
7395 if (!iblk->intervals[i].gcmarkbit) 7646 if (!iblk->intervals[i].gcmarkbit)
7396 { 7647 {
7397 set_interval_parent (&iblk->intervals[i], interval_free_list); 7648 set_interval_parent (&iblk->intervals[i], interval_free_list);
7398 interval_free_list = &iblk->intervals[i]; 7649 interval_free_list = &iblk->intervals[i];
7650 ASAN_POISON_INTERVAL (&iblk->intervals[i]);
7399 this_free++; 7651 this_free++;
7400 } 7652 }
7401 else 7653 else
@@ -7412,6 +7664,7 @@ sweep_intervals (void)
7412 { 7664 {
7413 *iprev = iblk->next; 7665 *iprev = iblk->next;
7414 /* Unhook from the free list. */ 7666 /* Unhook from the free list. */
7667 ASAN_UNPOISON_INTERVAL (&iblk->intervals[0]);
7415 interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]); 7668 interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]);
7416 lisp_free (iblk); 7669 lisp_free (iblk);
7417 } 7670 }
@@ -7441,6 +7694,8 @@ sweep_symbols (void)
7441 7694
7442 for (sblk = symbol_block; sblk; sblk = *sprev) 7695 for (sblk = symbol_block; sblk; sblk = *sprev)
7443 { 7696 {
7697 ASAN_UNPOISON_SYMBOL_BLOCK (sblk);
7698
7444 int this_free = 0; 7699 int this_free = 0;
7445 struct Lisp_Symbol *sym = sblk->symbols; 7700 struct Lisp_Symbol *sym = sblk->symbols;
7446 struct Lisp_Symbol *end = sym + lim; 7701 struct Lisp_Symbol *end = sym + lim;
@@ -7462,7 +7717,8 @@ sweep_symbols (void)
7462 sym->u.s.next = symbol_free_list; 7717 sym->u.s.next = symbol_free_list;
7463 symbol_free_list = sym; 7718 symbol_free_list = sym;
7464 symbol_free_list->u.s.function = dead_object (); 7719 symbol_free_list->u.s.function = dead_object ();
7465 ++this_free; 7720 ASAN_POISON_SYMBOL (sym);
7721 ++this_free;
7466 } 7722 }
7467 else 7723 else
7468 { 7724 {
@@ -7481,6 +7737,7 @@ sweep_symbols (void)
7481 { 7737 {
7482 *sprev = sblk->next; 7738 *sprev = sblk->next;
7483 /* Unhook from the free list. */ 7739 /* Unhook from the free list. */
7740 ASAN_UNPOISON_SYMBOL (&sblk->symbols[0]);
7484 symbol_free_list = sblk->symbols[0].u.s.next; 7741 symbol_free_list = sblk->symbols[0].u.s.next;
7485 lisp_free (sblk); 7742 lisp_free (sblk);
7486 } 7743 }
@@ -7548,9 +7805,17 @@ DEFUN ("memory-info", Fmemory_info, Smemory_info, 0, 0, 0,
7548 doc: /* Return a list of (TOTAL-RAM FREE-RAM TOTAL-SWAP FREE-SWAP). 7805 doc: /* Return a list of (TOTAL-RAM FREE-RAM TOTAL-SWAP FREE-SWAP).
7549All values are in Kbytes. If there is no swap space, 7806All values are in Kbytes. If there is no swap space,
7550last two values are zero. If the system is not supported 7807last two values are zero. If the system is not supported
7551or memory information can't be obtained, return nil. */) 7808or memory information can't be obtained, return nil.
7809If `default-directory’ is remote, return memory information of the
7810respective remote host. */)
7552 (void) 7811 (void)
7553{ 7812{
7813 Lisp_Object handler
7814 = Ffind_file_name_handler (BVAR (current_buffer, directory),
7815 Qmemory_info);
7816 if (!NILP (handler))
7817 return call1 (handler, Qmemory_info);
7818
7554#if defined HAVE_LINUX_SYSINFO 7819#if defined HAVE_LINUX_SYSINFO
7555 struct sysinfo si; 7820 struct sysinfo si;
7556 uintmax_t units; 7821 uintmax_t units;
@@ -7972,6 +8237,8 @@ do hash-consing of the objects allocated to pure space. */);
7972 doc: /* Non-nil means Emacs cannot get much more Lisp memory. */); 8237 doc: /* Non-nil means Emacs cannot get much more Lisp memory. */);
7973 Vmemory_full = Qnil; 8238 Vmemory_full = Qnil;
7974 8239
8240 DEFSYM (Qmemory_info, "memory-info");
8241
7975 DEFSYM (Qconses, "conses"); 8242 DEFSYM (Qconses, "conses");
7976 DEFSYM (Qsymbols, "symbols"); 8243 DEFSYM (Qsymbols, "symbols");
7977 DEFSYM (Qstrings, "strings"); 8244 DEFSYM (Qstrings, "strings");