diff options
| author | Vibhav Pant | 2022-12-20 21:56:02 +0530 |
|---|---|---|
| committer | Vibhav Pant | 2022-12-20 21:56:02 +0530 |
| commit | e7459fcbde4e468f9dfc74477072c7405b59e03e (patch) | |
| tree | 524457d1b9f6aa7edb393b540e4123d1fc60942b /src/alloc.c | |
| parent | 89892db0af4f8a803eb7ff3f5f7880d3126702ff (diff) | |
| parent | 9fafeb2a66fe1cba8f3ad7662196e36ca0b1eca7 (diff) | |
| download | emacs-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.c | 289 |
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. */ |
| 1168 | static struct ablock *free_ablock; | 1209 | static 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 | ||
| 1429 | static INTERVAL interval_free_list; | 1476 | static 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 | ||
| 1433 | INTERVAL | 1498 | INTERVAL |
| @@ -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 | ||
| 2606 | static struct float_block *float_block; | 2751 | static 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 | ||
| 2716 | static struct Lisp_Cons *cons_free_list; | 2864 | static 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 | ||
| 2720 | void | 2881 | void |
| @@ -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 | ||
| 2730 | DEFUN ("cons", Fcons, Scons, 2, 2, 0, | 2892 | DEFUN ("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 | ||
| 3006 | Lisp_Object zero_vector; | 3171 | Lisp_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 | ||
| 3010 | static void | 3188 | static 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 * | |||
| 4624 | live_string_holding (struct mem_node *m, void *p) | 4832 | live_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 * | |||
| 4661 | live_cons_holding (struct mem_node *m, void *p) | 4878 | live_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 * | |||
| 4700 | live_symbol_holding (struct mem_node *m, void *p) | 4926 | live_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 * | |||
| 4747 | live_float_holding (struct mem_node *m, void *p) | 4981 | live_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). |
| 7549 | All values are in Kbytes. If there is no swap space, | 7806 | All values are in Kbytes. If there is no swap space, |
| 7550 | last two values are zero. If the system is not supported | 7807 | last two values are zero. If the system is not supported |
| 7551 | or memory information can't be obtained, return nil. */) | 7808 | or memory information can't be obtained, return nil. |
| 7809 | If `default-directory’ is remote, return memory information of the | ||
| 7810 | respective 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"); |