aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2020-08-14 14:33:21 -0700
committerPaul Eggert2020-08-14 15:51:52 -0700
commit4ecc2ba01db5029c42d3b7f1418a021cccf2dc67 (patch)
treedbddc98222b1fbdb7d3af0f373d21fb3b2c73467 /src
parentca6c3bec0769d8ac7a49cdb8d2580add5485366e (diff)
downloademacs-4ecc2ba01db5029c42d3b7f1418a021cccf2dc67.tar.gz
emacs-4ecc2ba01db5029c42d3b7f1418a021cccf2dc67.zip
Fix bus error on Debian bullseye
Problem reported by Lars Ingebrigtsen, and problem diagnosis and most of this patch by Pip Cet (Bug#42832). * src/pdumper.c (dump_bitsets_init): Rename from dump_bitset_init. All callers changed. Initialize two bitsets with a single malloc call. (struct pdumper_loaded_dump_private): New member last_mark_bits. (pdumper_find_object_type_impl): Return PDUMPER_NO_OBJECT if the last_mark_bits’ bit is clear. (pdumper_set_marked_impl): Assert that the last_mark_bits’ bit is set. (pdumper_clear_marks_impl): Save mark_bits into last_mark_bits before clearing mark_bits. Co-authored-by: Pip Cet <pipcet@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/pdumper.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/src/pdumper.c b/src/pdumper.c
index bc41afc7c5a..2d1b19283c7 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -4802,14 +4802,19 @@ struct dump_bitset
4802}; 4802};
4803 4803
4804static bool 4804static bool
4805dump_bitset_init (struct dump_bitset *bitset, size_t number_bits) 4805dump_bitsets_init (struct dump_bitset bitset[2], size_t number_bits)
4806{ 4806{
4807 int xword_size = sizeof (bitset->bits[0]); 4807 int xword_size = sizeof (bitset[0].bits[0]);
4808 int bits_per_word = xword_size * CHAR_BIT; 4808 int bits_per_word = xword_size * CHAR_BIT;
4809 ptrdiff_t words_needed = divide_round_up (number_bits, bits_per_word); 4809 ptrdiff_t words_needed = divide_round_up (number_bits, bits_per_word);
4810 bitset->number_words = words_needed; 4810 dump_bitset_word *bits = calloc (words_needed, 2 * xword_size);
4811 bitset->bits = calloc (words_needed, xword_size); 4811 if (!bits)
4812 return bitset->bits != NULL; 4812 return false;
4813 bitset[0].bits = bits;
4814 bitset[0].number_words = bitset[1].number_words = words_needed;
4815 bitset[1].bits = memset (bits + words_needed, UCHAR_MAX,
4816 words_needed * xword_size);
4817 return true;
4813} 4818}
4814 4819
4815static dump_bitset_word * 4820static dump_bitset_word *
@@ -4870,7 +4875,7 @@ struct pdumper_loaded_dump_private
4870 /* Copy of the header we read from the dump. */ 4875 /* Copy of the header we read from the dump. */
4871 struct dump_header header; 4876 struct dump_header header;
4872 /* Mark bits for objects in the dump; used during GC. */ 4877 /* Mark bits for objects in the dump; used during GC. */
4873 struct dump_bitset mark_bits; 4878 struct dump_bitset mark_bits, last_mark_bits;
4874 /* Time taken to load the dump. */ 4879 /* Time taken to load the dump. */
4875 double load_time; 4880 double load_time;
4876 /* Dump file name. */ 4881 /* Dump file name. */
@@ -4993,6 +4998,10 @@ pdumper_find_object_type_impl (const void *obj)
4993 dump_off offset = ptrdiff_t_to_dump_off ((uintptr_t) obj - dump_public.start); 4998 dump_off offset = ptrdiff_t_to_dump_off ((uintptr_t) obj - dump_public.start);
4994 if (offset % DUMP_ALIGNMENT != 0) 4999 if (offset % DUMP_ALIGNMENT != 0)
4995 return PDUMPER_NO_OBJECT; 5000 return PDUMPER_NO_OBJECT;
5001 ptrdiff_t bitno = offset / DUMP_ALIGNMENT;
5002 if (offset < dump_private.header.cold_start
5003 && !dump_bitset_bit_set_p (&dump_private.last_mark_bits, bitno))
5004 return PDUMPER_NO_OBJECT;
4996 const struct dump_reloc *reloc = 5005 const struct dump_reloc *reloc =
4997 dump_find_relocation (&dump_private.header.object_starts, offset); 5006 dump_find_relocation (&dump_private.header.object_starts, offset);
4998 return (reloc != NULL && dump_reloc_get_offset (*reloc) == offset) 5007 return (reloc != NULL && dump_reloc_get_offset (*reloc) == offset)
@@ -5021,12 +5030,16 @@ pdumper_set_marked_impl (const void *obj)
5021 eassert (offset < dump_private.header.cold_start); 5030 eassert (offset < dump_private.header.cold_start);
5022 eassert (offset < dump_private.header.discardable_start); 5031 eassert (offset < dump_private.header.discardable_start);
5023 ptrdiff_t bitno = offset / DUMP_ALIGNMENT; 5032 ptrdiff_t bitno = offset / DUMP_ALIGNMENT;
5033 eassert (dump_bitset_bit_set_p (&dump_private.last_mark_bits, bitno));
5024 dump_bitset_set_bit (&dump_private.mark_bits, bitno); 5034 dump_bitset_set_bit (&dump_private.mark_bits, bitno);
5025} 5035}
5026 5036
5027void 5037void
5028pdumper_clear_marks_impl (void) 5038pdumper_clear_marks_impl (void)
5029{ 5039{
5040 dump_bitset_word *swap = dump_private.last_mark_bits.bits;
5041 dump_private.last_mark_bits.bits = dump_private.mark_bits.bits;
5042 dump_private.mark_bits.bits = swap;
5030 dump_bitset_clear (&dump_private.mark_bits); 5043 dump_bitset_clear (&dump_private.mark_bits);
5031} 5044}
5032 5045
@@ -5243,7 +5256,7 @@ pdumper_load (const char *dump_filename)
5243 int dump_page_size; 5256 int dump_page_size;
5244 dump_off adj_discardable_start; 5257 dump_off adj_discardable_start;
5245 5258
5246 struct dump_bitset mark_bits; 5259 struct dump_bitset mark_bits[2];
5247 size_t mark_bits_needed; 5260 size_t mark_bits_needed;
5248 5261
5249 struct dump_header header_buf = { 0 }; 5262 struct dump_header header_buf = { 0 };
@@ -5357,7 +5370,7 @@ pdumper_load (const char *dump_filename)
5357 err = PDUMPER_LOAD_ERROR; 5370 err = PDUMPER_LOAD_ERROR;
5358 mark_bits_needed = 5371 mark_bits_needed =
5359 divide_round_up (header->discardable_start, DUMP_ALIGNMENT); 5372 divide_round_up (header->discardable_start, DUMP_ALIGNMENT);
5360 if (!dump_bitset_init (&mark_bits, mark_bits_needed)) 5373 if (!dump_bitsets_init (mark_bits, mark_bits_needed))
5361 goto out; 5374 goto out;
5362 5375
5363 /* Point of no return. */ 5376 /* Point of no return. */
@@ -5365,7 +5378,8 @@ pdumper_load (const char *dump_filename)
5365 dump_base = (uintptr_t) sections[DS_HOT].mapping; 5378 dump_base = (uintptr_t) sections[DS_HOT].mapping;
5366 gflags.dumped_with_pdumper_ = true; 5379 gflags.dumped_with_pdumper_ = true;
5367 dump_private.header = *header; 5380 dump_private.header = *header;
5368 dump_private.mark_bits = mark_bits; 5381 dump_private.mark_bits = mark_bits[0];
5382 dump_private.last_mark_bits = mark_bits[1];
5369 dump_public.start = dump_base; 5383 dump_public.start = dump_base;
5370 dump_public.end = dump_public.start + dump_size; 5384 dump_public.end = dump_public.start + dump_size;
5371 5385