diff options
Diffstat (limited to 'src/pdumper.c')
| -rw-r--r-- | src/pdumper.c | 123 |
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)); | |||
| 135 | verify (sizeof (void (*)(void)) == sizeof (void *)); | 127 | verify (sizeof (void (*)(void)) == sizeof (void *)); |
| 136 | verify (sizeof (ptrdiff_t) <= sizeof (Lisp_Object)); | 128 | verify (sizeof (ptrdiff_t) <= sizeof (Lisp_Object)); |
| 137 | verify (sizeof (ptrdiff_t) <= sizeof (EMACS_INT)); | 129 | verify (sizeof (ptrdiff_t) <= sizeof (EMACS_INT)); |
| 138 | verify (sizeof (off_t) == sizeof (int32_t) | ||
| 139 | || sizeof (off_t) == sizeof (int64_t)); | ||
| 140 | verify (CHAR_BIT == 8); | 130 | verify (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]; |
| 158 | static int nr_remembered_data = 0; | 148 | static int nr_remembered_data = 0; |
| 159 | 149 | ||
| 160 | typedef int32_t dump_off; | 150 | typedef 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))) |
| 165 | static void | 155 | static void |
| @@ -302,10 +292,10 @@ verify (DUMP_ALIGNMENT >= GCALIGNMENT); | |||
| 302 | 292 | ||
| 303 | struct dump_reloc | 293 | struct 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 | }; |
| 308 | verify (sizeof (struct dump_reloc) == sizeof (int32_t)); | 298 | verify (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 | ||
| 337 | static void | 327 | static void |
| 338 | dump_fingerprint (const char *label, const uint8_t *xfingerprint) | 328 | dump_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 | |||
| 1780 | static dump_off | 1772 | static dump_off |
| 1781 | field_relpos (const void *in_start, const void *in_field) | 1773 | field_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, | |||
| 2760 | static dump_off | 2760 | static dump_off |
| 2761 | dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) | 2761 | dump_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 | ||
| 4312 | static void * | 4313 | static void * |
| 4313 | dump_anonymous_allocate_w32 (void *base, | 4314 | dump_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 | ||
| 4360 | static void * | 4357 | static void * |
| 4361 | dump_anonymous_allocate_posix (void *base, | 4358 | dump_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. */ |
| 4419 | static void * | 4410 | static 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 | ||
| 4453 | static void * | 4445 | static void * |
| 4454 | dump_map_file_w32 (void *base, int fd, off_t offset, size_t size, | 4446 | dump_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 | ||
| 4522 | static void * | 4507 | static void * |
| 4523 | dump_map_file_posix (void *base, int fd, off_t offset, size_t size, | 4508 | dump_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. */ |
| 4567 | static void * | 4544 | static void * |
| 4568 | dump_map_file (void *base, int fd, off_t offset, size_t size, | 4545 | dump_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. |