aboutsummaryrefslogtreecommitdiffstats
path: root/src/pdumper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pdumper.c')
-rw-r--r--src/pdumper.c123
1 files changed, 50 insertions, 73 deletions
diff --git a/src/pdumper.c b/src/pdumper.c
index 7fabfa771ce..600c5b3ca3d 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -46,7 +46,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
46#include "thread.h" 46#include "thread.h"
47#include "bignum.h" 47#include "bignum.h"
48 48
49#include "dmpstruct.h" 49#ifdef CHECK_STRUCTS
50# include "dmpstruct.h"
51#endif
50 52
51/* 53/*
52 TODO: 54 TODO:
@@ -68,16 +70,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
68 70
69#ifdef HAVE_PDUMPER 71#ifdef HAVE_PDUMPER
70 72
71/* CHECK_STRUCTS being true makes the build break if we notice
72 changes to the source defining certain Lisp structures we dump. If
73 you change one of these structures, check that the pdumper code is
74 still valid, and update the pertinent hash lower down in this file
75 (pdumper.c) by manually copying the value from the dmpstruct.h
76 generated from your new code. */
77#ifndef CHECK_STRUCTS
78# define CHECK_STRUCTS 1
79#endif
80
81#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) 73#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
82# pragma GCC diagnostic error "-Wconversion" 74# pragma GCC diagnostic error "-Wconversion"
83# pragma GCC diagnostic error "-Wshadow" 75# pragma GCC diagnostic error "-Wshadow"
@@ -135,8 +127,6 @@ verify (sizeof (intptr_t) == sizeof (ptrdiff_t));
135verify (sizeof (void (*)(void)) == sizeof (void *)); 127verify (sizeof (void (*)(void)) == sizeof (void *));
136verify (sizeof (ptrdiff_t) <= sizeof (Lisp_Object)); 128verify (sizeof (ptrdiff_t) <= sizeof (Lisp_Object));
137verify (sizeof (ptrdiff_t) <= sizeof (EMACS_INT)); 129verify (sizeof (ptrdiff_t) <= sizeof (EMACS_INT));
138verify (sizeof (off_t) == sizeof (int32_t)
139 || sizeof (off_t) == sizeof (int64_t));
140verify (CHAR_BIT == 8); 130verify (CHAR_BIT == 8);
141 131
142#define DIVIDE_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) 132#define DIVIDE_ROUND_UP(x, y) (((x) + (y) - 1) / (y))
@@ -157,9 +147,9 @@ static struct
157} remembered_data[32]; 147} remembered_data[32];
158static int nr_remembered_data = 0; 148static int nr_remembered_data = 0;
159 149
160typedef int32_t dump_off; 150typedef int_least32_t dump_off;
161#define DUMP_OFF_MIN INT32_MIN 151#define DUMP_OFF_MIN INT_LEAST32_MIN
162#define DUMP_OFF_MAX INT32_MAX 152#define DUMP_OFF_MAX INT_LEAST32_MAX
163 153
164__attribute__((format (printf,1,2))) 154__attribute__((format (printf,1,2)))
165static void 155static void
@@ -302,10 +292,10 @@ verify (DUMP_ALIGNMENT >= GCALIGNMENT);
302 292
303struct dump_reloc 293struct dump_reloc
304{ 294{
305 uint32_t raw_offset : DUMP_RELOC_OFFSET_BITS; 295 unsigned int raw_offset : DUMP_RELOC_OFFSET_BITS;
306 ENUM_BF (dump_reloc_type) type : DUMP_RELOC_TYPE_BITS; 296 ENUM_BF (dump_reloc_type) type : DUMP_RELOC_TYPE_BITS;
307}; 297};
308verify (sizeof (struct dump_reloc) == sizeof (int32_t)); 298verify (sizeof (struct dump_reloc) == sizeof (dump_off));
309 299
310/* Set the type of a dump relocation. 300/* Set the type of a dump relocation.
311 301
@@ -335,7 +325,7 @@ dump_reloc_set_offset (struct dump_reloc *reloc, dump_off offset)
335} 325}
336 326
337static void 327static void
338dump_fingerprint (const char *label, const uint8_t *xfingerprint) 328dump_fingerprint (const char *label, unsigned char const *xfingerprint)
339{ 329{
340 fprintf (stderr, "%s: ", label); 330 fprintf (stderr, "%s: ", label);
341 for (int i = 0; i < 32; ++i) 331 for (int i = 0; i < 32; ++i)
@@ -366,7 +356,7 @@ struct dump_header
366 char magic[sizeof (dump_magic)]; 356 char magic[sizeof (dump_magic)];
367 357
368 /* Associated Emacs binary. */ 358 /* Associated Emacs binary. */
369 uint8_t fingerprint[32]; 359 unsigned char fingerprint[32];
370 360
371 /* Relocation table for the dump file; each entry is a 361 /* Relocation table for the dump file; each entry is a
372 struct dump_reloc. */ 362 struct dump_reloc. */
@@ -1777,6 +1767,8 @@ dump_roots (struct dump_context *ctx)
1777 visit_static_gc_roots (visitor); 1767 visit_static_gc_roots (visitor);
1778} 1768}
1779 1769
1770#define PDUMPER_MAX_OBJECT_SIZE 2048
1771
1780static dump_off 1772static dump_off
1781field_relpos (const void *in_start, const void *in_field) 1773field_relpos (const void *in_start, const void *in_field)
1782{ 1774{
@@ -1784,7 +1776,15 @@ field_relpos (const void *in_start, const void *in_field)
1784 ptrdiff_t in_field_val = (ptrdiff_t) in_field; 1776 ptrdiff_t in_field_val = (ptrdiff_t) in_field;
1785 eassert (in_start_val <= in_field_val); 1777 eassert (in_start_val <= in_field_val);
1786 ptrdiff_t relpos = in_field_val - in_start_val; 1778 ptrdiff_t relpos = in_field_val - in_start_val;
1787 eassert (relpos < 1024); /* Sanity check. */ 1779 /* The following assertion attempts to detect bugs whereby IN_START
1780 and IN_FIELD don't point to the same object/structure, on the
1781 assumption that a too-large difference between them is
1782 suspicious. As of Apr 2019 the largest object we dump -- 'struct
1783 buffer' -- is slightly smaller than 1KB, and we want to leave
1784 some margin for future extensions. If the assertion below is
1785 ever violated, make sure the two pointers indeed point into the
1786 same object, and if so, enlarge the value of PDUMPER_MAX_OBJECT_SIZE. */
1787 eassert (relpos < PDUMPER_MAX_OBJECT_SIZE);
1788 return (dump_off) relpos; 1788 return (dump_off) relpos;
1789} 1789}
1790 1790
@@ -2692,7 +2692,7 @@ dump_hash_table (struct dump_context *ctx,
2692 Lisp_Object object, 2692 Lisp_Object object,
2693 dump_off offset) 2693 dump_off offset)
2694{ 2694{
2695#if CHECK_STRUCTS && !defined (HASH_Lisp_Hash_Table_73C9BFB7D1) 2695#if CHECK_STRUCTS && !defined HASH_Lisp_Hash_Table_EF95ED06FF
2696# error "Lisp_Hash_Table changed. See CHECK_STRUCTS comment." 2696# error "Lisp_Hash_Table changed. See CHECK_STRUCTS comment."
2697#endif 2697#endif
2698 const struct Lisp_Hash_Table *hash_in = XHASH_TABLE (object); 2698 const struct Lisp_Hash_Table *hash_in = XHASH_TABLE (object);
@@ -2760,7 +2760,7 @@ dump_hash_table (struct dump_context *ctx,
2760static dump_off 2760static dump_off
2761dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) 2761dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
2762{ 2762{
2763#if CHECK_STRUCTS && !defined HASH_buffer_2CEE653E74 2763#if CHECK_STRUCTS && !defined HASH_buffer_E34A11C6B9
2764# error "buffer changed. See CHECK_STRUCTS comment." 2764# error "buffer changed. See CHECK_STRUCTS comment."
2765#endif 2765#endif
2766 struct buffer munged_buffer = *in_buffer; 2766 struct buffer munged_buffer = *in_buffer;
@@ -4309,17 +4309,12 @@ enum dump_memory_protection
4309 DUMP_MEMORY_ACCESS_READWRITE = 3, 4309 DUMP_MEMORY_ACCESS_READWRITE = 3,
4310}; 4310};
4311 4311
4312#if VM_SUPPORTED == VM_MS_WINDOWS
4312static void * 4313static void *
4313dump_anonymous_allocate_w32 (void *base, 4314dump_anonymous_allocate_w32 (void *base,
4314 size_t size, 4315 size_t size,
4315 enum dump_memory_protection protection) 4316 enum dump_memory_protection protection)
4316{ 4317{
4317#if VM_SUPPORTED != VM_MS_WINDOWS
4318 (void) base;
4319 (void) size;
4320 (void) protection;
4321 emacs_abort ();
4322#else
4323 void *ret; 4318 void *ret;
4324 DWORD mem_type; 4319 DWORD mem_type;
4325 DWORD mem_prot; 4320 DWORD mem_prot;
@@ -4348,26 +4343,22 @@ dump_anonymous_allocate_w32 (void *base,
4348 ? EBUSY 4343 ? EBUSY
4349 : EPERM; 4344 : EPERM;
4350 return ret; 4345 return ret;
4351#endif
4352} 4346}
4347#endif
4348
4349#if VM_SUPPORTED == VM_POSIX
4353 4350
4354/* Old versions of macOS only define MAP_ANON, not MAP_ANONYMOUS. 4351/* Old versions of macOS only define MAP_ANON, not MAP_ANONYMOUS.
4355 FIXME: This probably belongs elsewhere (gnulib/autoconf?) */ 4352 FIXME: This probably belongs elsewhere (gnulib/autoconf?) */
4356#ifndef MAP_ANONYMOUS 4353# ifndef MAP_ANONYMOUS
4357#define MAP_ANONYMOUS MAP_ANON 4354# define MAP_ANONYMOUS MAP_ANON
4358#endif 4355# endif
4359 4356
4360static void * 4357static void *
4361dump_anonymous_allocate_posix (void *base, 4358dump_anonymous_allocate_posix (void *base,
4362 size_t size, 4359 size_t size,
4363 enum dump_memory_protection protection) 4360 enum dump_memory_protection protection)
4364{ 4361{
4365#if VM_SUPPORTED != VM_POSIX
4366 (void) base;
4367 (void) size;
4368 (void) protection;
4369 emacs_abort ();
4370#else
4371 void *ret; 4362 void *ret;
4372 int mem_prot; 4363 int mem_prot;
4373 4364
@@ -4412,8 +4403,8 @@ dump_anonymous_allocate_posix (void *base,
4412 if (ret == MAP_FAILED) 4403 if (ret == MAP_FAILED)
4413 ret = NULL; 4404 ret = NULL;
4414 return ret; 4405 return ret;
4415#endif
4416} 4406}
4407#endif
4417 4408
4418/* Perform anonymous memory allocation. */ 4409/* Perform anonymous memory allocation. */
4419static void * 4410static void *
@@ -4421,14 +4412,14 @@ dump_anonymous_allocate (void *base,
4421 const size_t size, 4412 const size_t size,
4422 enum dump_memory_protection protection) 4413 enum dump_memory_protection protection)
4423{ 4414{
4424 void *ret = NULL; 4415#if VM_SUPPORTED == VM_POSIX
4425 if (VM_SUPPORTED == VM_MS_WINDOWS) 4416 return dump_anonymous_allocate_posix (base, size, protection);
4426 ret = dump_anonymous_allocate_w32 (base, size, protection); 4417#elif VM_SUPPORTED == VM_MS_WINDOWS
4427 else if (VM_SUPPORTED == VM_POSIX) 4418 return dump_anonymous_allocate_w32 (base, size, protection);
4428 ret = dump_anonymous_allocate_posix (base, size, protection); 4419#else
4429 else 4420 errno = ENOSYS;
4430 errno = ENOSYS; 4421 return NULL;
4431 return ret; 4422#endif
4432} 4423}
4433 4424
4434/* Undo the effect of dump_reserve_address_space(). */ 4425/* Undo the effect of dump_reserve_address_space(). */
@@ -4450,18 +4441,11 @@ dump_anonymous_release (void *addr, size_t size)
4450#endif 4441#endif
4451} 4442}
4452 4443
4444#if VM_SUPPORTED == VM_MS_WINDOWS
4453static void * 4445static void *
4454dump_map_file_w32 (void *base, int fd, off_t offset, size_t size, 4446dump_map_file_w32 (void *base, int fd, off_t offset, size_t size,
4455 enum dump_memory_protection protection) 4447 enum dump_memory_protection protection)
4456{ 4448{
4457#if VM_SUPPORTED != VM_MS_WINDOWS
4458 (void) base;
4459 (void) fd;
4460 (void) offset;
4461 (void) size;
4462 (void) protection;
4463 emacs_abort ();
4464#else
4465 void *ret = NULL; 4449 void *ret = NULL;
4466 HANDLE section = NULL; 4450 HANDLE section = NULL;
4467 HANDLE file; 4451 HANDLE file;
@@ -4516,21 +4500,14 @@ dump_map_file_w32 (void *base, int fd, off_t offset, size_t size,
4516 if (section && !CloseHandle (section)) 4500 if (section && !CloseHandle (section))
4517 emacs_abort (); 4501 emacs_abort ();
4518 return ret; 4502 return ret;
4519#endif
4520} 4503}
4504#endif
4521 4505
4506#if VM_SUPPORTED == VM_POSIX
4522static void * 4507static void *
4523dump_map_file_posix (void *base, int fd, off_t offset, size_t size, 4508dump_map_file_posix (void *base, int fd, off_t offset, size_t size,
4524 enum dump_memory_protection protection) 4509 enum dump_memory_protection protection)
4525{ 4510{
4526#if VM_SUPPORTED != VM_POSIX
4527 (void) base;
4528 (void) fd;
4529 (void) offset;
4530 (void) size;
4531 (void) protection;
4532 emacs_abort ();
4533#else
4534 void *ret; 4511 void *ret;
4535 int mem_prot; 4512 int mem_prot;
4536 int mem_flags; 4513 int mem_flags;
@@ -4560,22 +4537,22 @@ dump_map_file_posix (void *base, int fd, off_t offset, size_t size,
4560 if (ret == MAP_FAILED) 4537 if (ret == MAP_FAILED)
4561 ret = NULL; 4538 ret = NULL;
4562 return ret; 4539 return ret;
4563#endif
4564} 4540}
4541#endif
4565 4542
4566/* Map a file into memory. */ 4543/* Map a file into memory. */
4567static void * 4544static void *
4568dump_map_file (void *base, int fd, off_t offset, size_t size, 4545dump_map_file (void *base, int fd, off_t offset, size_t size,
4569 enum dump_memory_protection protection) 4546 enum dump_memory_protection protection)
4570{ 4547{
4571 void *ret = NULL; 4548#if VM_SUPPORTED == VM_POSIX
4572 if (VM_SUPPORTED == VM_MS_WINDOWS) 4549 return dump_map_file_posix (base, fd, offset, size, protection);
4573 ret = dump_map_file_w32 (base, fd, offset, size, protection); 4550#elif VM_SUPPORTED == VM_MS_WINDOWS
4574 else if (VM_SUPPORTED == VM_POSIX) 4551 return dump_map_file_w32 (base, fd, offset, size, protection);
4575 ret = dump_map_file_posix (base, fd, offset, size, protection); 4552#else
4576 else 4553 errno = ENOSYS;
4577 errno = ENOSYS;
4578 return ret; 4554 return ret;
4555#endif
4579} 4556}
4580 4557
4581/* Remove a virtual memory mapping. 4558/* Remove a virtual memory mapping.