aboutsummaryrefslogtreecommitdiffstats
path: root/src/pdumper.c
diff options
context:
space:
mode:
authorPo Lu2025-03-09 23:02:21 +0800
committerPo Lu2025-03-09 23:07:33 +0800
commita5f8ce9f1eae29f87fe13adb61bd4e15faa628a2 (patch)
tree602dba32bf3efcd7743f0d2df5e73339d98a5b2e /src/pdumper.c
parent57cef07710d91988b6332ad3ed2f5c4b4b371585 (diff)
downloademacs-a5f8ce9f1eae29f87fe13adb61bd4e15faa628a2.tar.gz
emacs-a5f8ce9f1eae29f87fe13adb61bd4e15faa628a2.zip
Re-port to 32-bit systems without alignment primitives
* configure.ac (ALIGNOF_INT, ALIGNOF_LONG, ALIGNOF_LONG_LONG): New variables. (emacs_cv_alignas_unavailable): Define if alignas and structure alignment primitives are unavailable. In such an environment, the MSB tagging scheme must be enabled, as must the GNU malloc. * msdos/sed2v2.inp: Adjust correspondingly. * src/alloc.c (union emacs_align_type): Remove types which contain flexible array members. The address of a field subsequent to an aggregate with flexible array members cannot validly be taken. (mark_memory) [!USE_LSB_TAG && !WIDE_EMACS_INT]: Strip type bits before scanning memory. * src/emacs.c (main): * src/eval.c (Fautoload_do_load): * src/fns.c (Frequire): Rename a number of illogically named fields. * src/lisp.h (ALIGNOF_EMACS_INT): Define to the natural alignment of EMACS_INT. (IDEAL_GCALIGNMENT): New macro. (USE_LSB_TAG): Disable if no alignment specifiers are available, WIDE_EMACS_INT is undefined, and the natural alignment of EMACS_INT falls short of LSB tagging's requirements. (gflags): Rename illogically named fields and don't define them as bitfields, which runs afoul of certain compiler issues. (will_dump_p, will_bootstrap_p, will_dump_with_pdumper_p) (dumped_with_pdumper_p): Adjust accordingly. * src/pdumper.c (VM_SUPPORTED): Define to 0 when !USE_LSB_TAG. It is better to read dump files into the heap by hand than to be supplied with an address that is not representable. (_dump_object_start_pseudovector): Rename to dump_object_start_pseudovector, to avoid encroaching on reserved names. (START_DUMP_PVEC): Adjust correspondingly. (dump_mmap_contiguous_vm): Preserve errno around failure cleanup. (dump_bitset_bit_set_p): Work around certain compiler issues. (pdumper_load) [!USE_LSB_TAG]: Reject dump file allocations that are not representable as Lisp_Objects. Tested on i386-unknown-solaris2.10, sparc-sun-solaris2.10.
Diffstat (limited to 'src/pdumper.c')
-rw-r--r--src/pdumper.c141
1 files changed, 83 insertions, 58 deletions
diff --git a/src/pdumper.c b/src/pdumper.c
index 342c37b5e62..8e10e561bcf 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -77,7 +77,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
77#define VM_POSIX 1 77#define VM_POSIX 1
78#define VM_MS_WINDOWS 2 78#define VM_MS_WINDOWS 2
79 79
80#if defined (HAVE_MMAP) && defined (MAP_FIXED) 80#if !USE_LSB_TAG
81# define VM_SUPPORTED 0
82#elif defined (HAVE_MMAP) && defined (MAP_FIXED)
81# define VM_SUPPORTED VM_POSIX 83# define VM_SUPPORTED VM_POSIX
82# if !defined (MAP_POPULATE) && defined (MAP_PREFAULT_READ) 84# if !defined (MAP_POPULATE) && defined (MAP_PREFAULT_READ)
83# define MAP_POPULATE MAP_PREFAULT_READ 85# define MAP_POPULATE MAP_PREFAULT_READ
@@ -1964,9 +1966,9 @@ dump_field_emacs_ptr (struct dump_context *ctx,
1964} 1966}
1965 1967
1966static void 1968static void
1967_dump_object_start_pseudovector (struct dump_context *ctx, 1969dump_object_start_pseudovector (struct dump_context *ctx,
1968 union vectorlike_header *out_hdr, 1970 union vectorlike_header *out_hdr,
1969 const union vectorlike_header *in_hdr) 1971 const union vectorlike_header *in_hdr)
1970{ 1972{
1971 eassert (in_hdr->size & PSEUDOVECTOR_FLAG); 1973 eassert (in_hdr->size & PSEUDOVECTOR_FLAG);
1972 ptrdiff_t vec_size = vectorlike_nbytes (in_hdr); 1974 ptrdiff_t vec_size = vectorlike_nbytes (in_hdr);
@@ -1976,9 +1978,9 @@ _dump_object_start_pseudovector (struct dump_context *ctx,
1976 1978
1977/* Need a macro for alloca. */ 1979/* Need a macro for alloca. */
1978#define START_DUMP_PVEC(ctx, hdr, type, out) \ 1980#define START_DUMP_PVEC(ctx, hdr, type, out) \
1979 const union vectorlike_header *_in_hdr = (hdr); \ 1981 const union vectorlike_header *in_hdr = (hdr); \
1980 type *out = alloca (vectorlike_nbytes (_in_hdr)); \ 1982 type *out = alloca (vectorlike_nbytes (in_hdr)); \
1981 _dump_object_start_pseudovector (ctx, &out->header, _in_hdr) 1983 dump_object_start_pseudovector (ctx, &out->header, in_hdr)
1982 1984
1983static dump_off 1985static dump_off
1984finish_dump_pvec (struct dump_context *ctx, 1986finish_dump_pvec (struct dump_context *ctx,
@@ -3994,14 +3996,14 @@ dump_do_fixup (struct dump_context *ctx,
3994 Lisp_Object fixup, 3996 Lisp_Object fixup,
3995 Lisp_Object prev_fixup) 3997 Lisp_Object prev_fixup)
3996{ 3998{
3997 enum dump_fixup_type type = 3999 enum dump_fixup_type type
3998 (enum dump_fixup_type) XFIXNUM (dump_pop (&fixup)); 4000 = (enum dump_fixup_type) XFIXNUM (dump_pop (&fixup));
3999 dump_off dump_fixup_offset = dump_off_from_lisp (dump_pop (&fixup)); 4001 dump_off dump_fixup_offset = dump_off_from_lisp (dump_pop (&fixup));
4000#ifdef ENABLE_CHECKING 4002#ifdef ENABLE_CHECKING
4001 if (!NILP (prev_fixup)) 4003 if (!NILP (prev_fixup))
4002 { 4004 {
4003 dump_off prev_dump_fixup_offset = 4005 dump_off prev_dump_fixup_offset
4004 dump_off_from_lisp (XCAR (XCDR (prev_fixup))); 4006 = dump_off_from_lisp (XCAR (XCDR (prev_fixup)));
4005 eassert (dump_fixup_offset - prev_dump_fixup_offset 4007 eassert (dump_fixup_offset - prev_dump_fixup_offset
4006 >= sizeof (void *)); 4008 >= sizeof (void *));
4007 } 4009 }
@@ -4618,23 +4620,8 @@ dump_anonymous_allocate_posix (void *base,
4618} 4620}
4619#endif 4621#endif
4620 4622
4621/* Perform anonymous memory allocation. */ 4623/* Undo the effect of `dump_reserve_address_space'. */
4622static void *
4623dump_anonymous_allocate (void *base,
4624 const size_t size,
4625 enum dump_memory_protection protection)
4626{
4627#if VM_SUPPORTED == VM_POSIX
4628 return dump_anonymous_allocate_posix (base, size, protection);
4629#elif VM_SUPPORTED == VM_MS_WINDOWS
4630 return dump_anonymous_allocate_w32 (base, size, protection);
4631#else
4632 errno = ENOSYS;
4633 return NULL;
4634#endif
4635}
4636 4624
4637/* Undo the effect of dump_reserve_address_space(). */
4638static void 4625static void
4639dump_anonymous_release (void *addr, size_t size) 4626dump_anonymous_release (void *addr, size_t size)
4640{ 4627{
@@ -4653,6 +4640,26 @@ dump_anonymous_release (void *addr, size_t size)
4653#endif 4640#endif
4654} 4641}
4655 4642
4643/* Perform anonymous memory allocation. */
4644static void *
4645dump_anonymous_allocate (void *base,
4646 const size_t size,
4647 enum dump_memory_protection protection)
4648{
4649 void *val;
4650
4651#if VM_SUPPORTED == VM_POSIX
4652 val = dump_anonymous_allocate_posix (base, size, protection);
4653#elif VM_SUPPORTED == VM_MS_WINDOWS
4654 val = dump_anonymous_allocate_w32 (base, size, protection);
4655#else
4656 errno = ENOSYS;
4657 val = NULL;
4658#endif
4659
4660 return val;
4661}
4662
4656#if VM_SUPPORTED == VM_MS_WINDOWS 4663#if VM_SUPPORTED == VM_MS_WINDOWS
4657static void * 4664static void *
4658dump_map_file_w32 (void *base, int fd, off_t offset, size_t size, 4665dump_map_file_w32 (void *base, int fd, off_t offset, size_t size,
@@ -4824,20 +4831,20 @@ static void
4824dump_discard_mem (void *mem, size_t size) 4831dump_discard_mem (void *mem, size_t size)
4825{ 4832{
4826#if VM_SUPPORTED == VM_MS_WINDOWS 4833#if VM_SUPPORTED == VM_MS_WINDOWS
4827 /* Discard COWed pages. */ 4834 /* Discard COWed pages. */
4828 (void) VirtualFree (mem, size, MEM_DECOMMIT); 4835 (void) VirtualFree (mem, size, MEM_DECOMMIT);
4829 /* Release the commit charge for the mapping. */ 4836 /* Release the commit charge for the mapping. */
4830 DWORD old_prot; 4837 DWORD old_prot;
4831 (void) VirtualProtect (mem, size, PAGE_NOACCESS, &old_prot); 4838 (void) VirtualProtect (mem, size, PAGE_NOACCESS, &old_prot);
4832#elif VM_SUPPORTED == VM_POSIX 4839#elif VM_SUPPORTED == VM_POSIX
4833# ifdef HAVE_POSIX_MADVISE 4840# ifdef HAVE_POSIX_MADVISE
4834 /* Discard COWed pages. */ 4841 /* Discard COWed pages. */
4835 (void) posix_madvise (mem, size, POSIX_MADV_DONTNEED); 4842 (void) posix_madvise (mem, size, POSIX_MADV_DONTNEED);
4836# elif defined HAVE_MADVISE 4843# elif defined HAVE_MADVISE
4837 (void) madvise (mem, size, MADV_DONTNEED); 4844 (void) madvise (mem, size, MADV_DONTNEED);
4838#endif 4845#endif
4839 /* Release the commit charge for the mapping. */ 4846 /* Release the commit charge for the mapping. */
4840 (void) mprotect (mem, size, PROT_NONE); 4847 (void) mprotect (mem, size, PROT_NONE);
4841#endif 4848#endif
4842} 4849}
4843 4850
@@ -4959,21 +4966,23 @@ dump_mmap_release_vm (struct dump_memory_map *map)
4959static bool 4966static bool
4960needs_mmap_retry_p (void) 4967needs_mmap_retry_p (void)
4961{ 4968{
4962#if defined CYGWIN || VM_SUPPORTED == VM_MS_WINDOWS || defined _AIX 4969#if defined CYGWIN || VM_SUPPORTED == VM_MS_WINDOWS \
4970 || defined _AIX
4963 return true; 4971 return true;
4964#else 4972#else /* !CYGWIN && VM_SUPPORTED != VM_MS_WINDOWS && !_AIX */
4965 return false; 4973 return false;
4966#endif 4974#endif /* !CYGWIN && VM_SUPPORTED != VM_MS_WINDOWS && !_AIX */
4967} 4975}
4968 4976
4969static bool 4977static bool
4970dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps, 4978dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps,
4971 size_t total_size) 4979 size_t total_size)
4972{ 4980{
4981 int save_errno;
4973 bool ret = false; 4982 bool ret = false;
4974 void *resv = NULL; 4983 void *resv = NULL;
4975 bool retry = false; 4984 bool retry = false;
4976 const bool need_retry = needs_mmap_retry_p (); 4985 bool need_retry = needs_mmap_retry_p ();
4977 4986
4978 do 4987 do
4979 { 4988 {
@@ -4986,11 +4995,10 @@ dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps,
4986 } 4995 }
4987 4996
4988 eassert (resv == NULL); 4997 eassert (resv == NULL);
4989 resv = dump_anonymous_allocate (NULL, 4998 resv = dump_anonymous_allocate (NULL, total_size,
4990 total_size,
4991 DUMP_MEMORY_ACCESS_NONE); 4999 DUMP_MEMORY_ACCESS_NONE);
4992 if (!resv) 5000 if (!resv)
4993 goto out; 5001 goto out;
4994 5002
4995 char *mem = resv; 5003 char *mem = resv;
4996 5004
@@ -5039,6 +5047,7 @@ dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps,
5039 ret = true; 5047 ret = true;
5040 resv = NULL; 5048 resv = NULL;
5041 out: 5049 out:
5050 save_errno = errno;
5042 if (resv) 5051 if (resv)
5043 dump_anonymous_release (resv, total_size); 5052 dump_anonymous_release (resv, total_size);
5044 if (!ret) 5053 if (!ret)
@@ -5051,6 +5060,7 @@ dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps,
5051 dump_mmap_release (&maps[i]); 5060 dump_mmap_release (&maps[i]);
5052 } 5061 }
5053 } 5062 }
5063 errno = save_errno;
5054 return ret; 5064 return ret;
5055} 5065}
5056 5066
@@ -5058,8 +5068,8 @@ dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps,
5058 5068
5059 Each dump_memory_map structure describes how to fill the 5069 Each dump_memory_map structure describes how to fill the
5060 corresponding range of memory. On input, all members except MAPPING 5070 corresponding range of memory. On input, all members except MAPPING
5061 are valid. On output, MAPPING contains the location of the given 5071 are valid. On output, MAPPING contains the location of the given
5062 chunk of memory. The MAPPING for MAPS[N] is MAPS[N-1].mapping + 5072 chunk of memory. The MAPPING for MAPS[N] is MAPS[N-1].mapping +
5063 MAPS[N-1].size. 5073 MAPS[N-1].size.
5064 5074
5065 Each mapping SIZE must be a multiple of the system page size except 5075 Each mapping SIZE must be a multiple of the system page size except
@@ -5085,8 +5095,10 @@ dump_mmap_contiguous (struct dump_memory_map *maps, int nr_maps)
5085 total_size += maps[i].spec.size; 5095 total_size += maps[i].spec.size;
5086 } 5096 }
5087 5097
5088 return (VM_SUPPORTED ? dump_mmap_contiguous_vm : dump_mmap_contiguous_heap) 5098 if (VM_SUPPORTED)
5089 (maps, nr_maps, total_size); 5099 return dump_mmap_contiguous_vm (maps, nr_maps, total_size);
5100 else
5101 return dump_mmap_contiguous_heap (maps, nr_maps, total_size);
5090} 5102}
5091 5103
5092typedef uint_fast32_t dump_bitset_word; 5104typedef uint_fast32_t dump_bitset_word;
@@ -5129,7 +5141,7 @@ dump_bitset_bit_set_p (const struct dump_bitset *bitset,
5129{ 5141{
5130 dump_bitset_word bit = 1; 5142 dump_bitset_word bit = 1;
5131 bit <<= bit_number % DUMP_BITSET_WORD_WIDTH; 5143 bit <<= bit_number % DUMP_BITSET_WORD_WIDTH;
5132 return *dump_bitset__bit_slot (bitset, bit_number) & bit; 5144 return (*dump_bitset__bit_slot (bitset, bit_number) & bit) != 0;
5133} 5145}
5134 5146
5135static void 5147static void
@@ -5548,8 +5560,8 @@ dump_do_dump_relocation (const uintptr_t dump_base,
5548 struct bignum_reload_info reload_info; 5560 struct bignum_reload_info reload_info;
5549 static_assert (sizeof (reload_info) <= sizeof (*bignum_val (bignum))); 5561 static_assert (sizeof (reload_info) <= sizeof (*bignum_val (bignum)));
5550 memcpy (&reload_info, bignum_val (bignum), sizeof (reload_info)); 5562 memcpy (&reload_info, bignum_val (bignum), sizeof (reload_info));
5551 const mp_limb_t *limbs = 5563 const mp_limb_t *limbs = dump_ptr (dump_base,
5552 dump_ptr (dump_base, reload_info.data_location); 5564 reload_info.data_location);
5553 mpz_roinit_n (bignum->value, limbs, reload_info.nlimbs); 5565 mpz_roinit_n (bignum->value, limbs, reload_info.nlimbs);
5554 break; 5566 break;
5555 } 5567 }
@@ -5790,15 +5802,29 @@ pdumper_load (const char *dump_filename, char *argv0)
5790 goto out; 5802 goto out;
5791 5803
5792 err = PDUMPER_LOAD_ERROR; 5804 err = PDUMPER_LOAD_ERROR;
5793 mark_bits_needed = 5805 dump_base = (uintptr_t) sections[DS_HOT].mapping;
5794 divide_round_up (header->discardable_start, DUMP_ALIGNMENT); 5806
5807#if !USE_LSB_TAG
5808 /* The dump may have been mapped at a location that does not admit of
5809 representation as Lisp_Objects. Abort in this case. */
5810 if ((dump_base + dump_size) & ~VALMASK)
5811 {
5812 fprintf (stderr,
5813 "Failed to load dump file: 0x%p+0x%p & 0x%p != 0\n",
5814 (void *) dump_base, (void *) dump_size,
5815 (void *) (uintptr_t) VALMASK);
5816 goto out;
5817 }
5818#endif /* !USE_LSB_TAG */
5819
5820 mark_bits_needed
5821 = divide_round_up (header->discardable_start, DUMP_ALIGNMENT);
5795 if (!dump_bitsets_init (mark_bits, mark_bits_needed)) 5822 if (!dump_bitsets_init (mark_bits, mark_bits_needed))
5796 goto out; 5823 goto out;
5797 5824
5798 /* Point of no return. */ 5825 /* Point of no return. */
5799 err = PDUMPER_LOAD_SUCCESS; 5826 err = PDUMPER_LOAD_SUCCESS;
5800 dump_base = (uintptr_t) sections[DS_HOT].mapping; 5827 gflags.dumped_with_pdumper = true;
5801 gflags.dumped_with_pdumper_ = true;
5802 dump_private.header = *header; 5828 dump_private.header = *header;
5803 dump_private.mark_bits = mark_bits[0]; 5829 dump_private.mark_bits = mark_bits[0];
5804 dump_private.last_mark_bits = mark_bits[1]; 5830 dump_private.last_mark_bits = mark_bits[1];
@@ -5815,8 +5841,8 @@ pdumper_load (const char *dump_filename, char *argv0)
5815 Lisp_Object hashes = zero_vector; 5841 Lisp_Object hashes = zero_vector;
5816 if (header->hash_list) 5842 if (header->hash_list)
5817 { 5843 {
5818 struct Lisp_Vector *hash_tables = 5844 struct Lisp_Vector *hash_tables
5819 (struct Lisp_Vector *) (dump_base + header->hash_list); 5845 = (struct Lisp_Vector *) (dump_base + header->hash_list);
5820 hashes = make_lisp_ptr (hash_tables, Lisp_Vectorlike); 5846 hashes = make_lisp_ptr (hash_tables, Lisp_Vectorlike);
5821 } 5847 }
5822 5848
@@ -5852,7 +5878,6 @@ pdumper_load (const char *dump_filename, char *argv0)
5852 dump_mmap_release (&sections[i]); 5878 dump_mmap_release (&sections[i]);
5853 if (dump_fd >= 0) 5879 if (dump_fd >= 0)
5854 emacs_close (dump_fd); 5880 emacs_close (dump_fd);
5855
5856 return err; 5881 return err;
5857} 5882}
5858 5883