aboutsummaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/alloc.c22
-rw-r--r--src/emacs.c12
-rw-r--r--src/eval.c2
-rw-r--r--src/fns.c2
-rw-r--r--src/lisp.h34
-rw-r--r--src/pdumper.c141
6 files changed, 130 insertions, 83 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 7fa05e54202..c0d68e6c964 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -150,8 +150,6 @@ union emacs_align_type
150{ 150{
151 struct frame frame; 151 struct frame frame;
152 struct Lisp_Bignum Lisp_Bignum; 152 struct Lisp_Bignum Lisp_Bignum;
153 struct Lisp_Bool_Vector Lisp_Bool_Vector;
154 struct Lisp_Char_Table Lisp_Char_Table;
155 struct Lisp_CondVar Lisp_CondVar; 153 struct Lisp_CondVar Lisp_CondVar;
156 struct Lisp_Finalizer Lisp_Finalizer; 154 struct Lisp_Finalizer Lisp_Finalizer;
157 struct Lisp_Float Lisp_Float; 155 struct Lisp_Float Lisp_Float;
@@ -160,21 +158,25 @@ union emacs_align_type
160 struct Lisp_Misc_Ptr Lisp_Misc_Ptr; 158 struct Lisp_Misc_Ptr Lisp_Misc_Ptr;
161 struct Lisp_Mutex Lisp_Mutex; 159 struct Lisp_Mutex Lisp_Mutex;
162 struct Lisp_Overlay Lisp_Overlay; 160 struct Lisp_Overlay Lisp_Overlay;
163 struct Lisp_Sub_Char_Table Lisp_Sub_Char_Table;
164 struct Lisp_Subr Lisp_Subr; 161 struct Lisp_Subr Lisp_Subr;
165 struct Lisp_Sqlite Lisp_Sqlite; 162 struct Lisp_Sqlite Lisp_Sqlite;
166 struct Lisp_User_Ptr Lisp_User_Ptr; 163 struct Lisp_User_Ptr Lisp_User_Ptr;
167 struct Lisp_Vector Lisp_Vector;
168 struct terminal terminal; 164 struct terminal terminal;
169 struct thread_state thread_state; 165 struct thread_state thread_state;
170 struct window window; 166 struct window window;
171 167
172 /* Omit the following since they would require including process.h 168 /* Omit the following since they would require including process.h
173 etc. In practice their alignments never exceed that of the 169 etc, or because they are defined with flexible array members, which
174 structs already listed. */ 170 are rejected by some C99 compilers when this union subsequently
171 appears in an `alignof' expression. In practice their alignments
172 never exceed that of the structs already listed. */
175#if 0 173#if 0
174 struct Lisp_Bool_Vector Lisp_Bool_Vector;
175 struct Lisp_Char_Table Lisp_Char_Table;
176 struct Lisp_Sub_Char_Table Lisp_Sub_Char_Table;
176 struct Lisp_Module_Function Lisp_Module_Function; 177 struct Lisp_Module_Function Lisp_Module_Function;
177 struct Lisp_Process Lisp_Process; 178 struct Lisp_Process Lisp_Process;
179 struct Lisp_Vector Lisp_Vector;
178 struct save_window_data save_window_data; 180 struct save_window_data save_window_data;
179 struct scroll_bar scroll_bar; 181 struct scroll_bar scroll_bar;
180 struct xwidget_view xwidget_view; 182 struct xwidget_view xwidget_view;
@@ -5167,14 +5169,20 @@ mark_memory (void const *start, void const *end)
5167 for (pp = start; (void const *) pp < end; pp += GC_POINTER_ALIGNMENT) 5169 for (pp = start; (void const *) pp < end; pp += GC_POINTER_ALIGNMENT)
5168 { 5170 {
5169 void *p = *(void *const *) pp; 5171 void *p = *(void *const *) pp;
5172 intptr_t ip;
5173
5174#if !USE_LSB_TAG && !defined WIDE_EMACS_INT
5175 ip = (intptr_t) p;
5176 mark_maybe_pointer ((void *) (ip & VALMASK), false);
5177#else /* USE_LSB_TAG || WIDE_EMACS_INT */
5170 mark_maybe_pointer (p, false); 5178 mark_maybe_pointer (p, false);
5179#endif /* USE_LSB_TAG || WIDE_EMACS_INT */
5171 5180
5172 /* Unmask any struct Lisp_Symbol pointer that make_lisp_symbol 5181 /* Unmask any struct Lisp_Symbol pointer that make_lisp_symbol
5173 previously disguised by adding the address of 'lispsym'. 5182 previously disguised by adding the address of 'lispsym'.
5174 On a host with 32-bit pointers and 64-bit Lisp_Objects, 5183 On a host with 32-bit pointers and 64-bit Lisp_Objects,
5175 a Lisp_Object might be split into registers saved into 5184 a Lisp_Object might be split into registers saved into
5176 non-adjacent words and P might be the low-order word's value. */ 5185 non-adjacent words and P might be the low-order word's value. */
5177 intptr_t ip;
5178 ckd_add (&ip, (intptr_t) p, (intptr_t) lispsym); 5186 ckd_add (&ip, (intptr_t) p, (intptr_t) lispsym);
5179 mark_maybe_pointer ((void *) ip, true); 5187 mark_maybe_pointer ((void *) ip, true);
5180 } 5188 }
diff --git a/src/emacs.c b/src/emacs.c
index dc7041c2338..6ff7b632c0f 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1311,13 +1311,11 @@ android_emacs_init (int argc, char **argv, char *dump_file)
1311 if (!initialized && temacs) 1311 if (!initialized && temacs)
1312 { 1312 {
1313#ifdef HAVE_PDUMPER 1313#ifdef HAVE_PDUMPER
1314 if (strcmp (temacs, "pdump") == 0 || 1314 if (!strcmp (temacs, "pdump") || !strcmp (temacs, "pbootstrap"))
1315 strcmp (temacs, "pbootstrap") == 0) 1315 gflags.will_dump_with_pdumper = true;
1316 gflags.will_dump_with_pdumper_ = true; 1316 if (!strcmp (temacs, "pbootstrap"))
1317 if (strcmp (temacs, "pbootstrap") == 0) 1317 gflags.will_bootstrap = true;
1318 gflags.will_bootstrap_ = true; 1318 gflags.will_dump = will_dump_with_pdumper_p ();
1319 gflags.will_dump_ =
1320 will_dump_with_pdumper_p ();
1321 if (will_dump_p ()) 1319 if (will_dump_p ())
1322 dump_mode = temacs; 1320 dump_mode = temacs;
1323#endif 1321#endif
diff --git a/src/eval.c b/src/eval.c
index a514bb4b8f9..5de723cf3bc 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2389,7 +2389,7 @@ it defines a macro. */)
2389 { 2389 {
2390 /* Avoid landing here recursively while outputting the 2390 /* Avoid landing here recursively while outputting the
2391 backtrace from the error. */ 2391 backtrace from the error. */
2392 gflags.will_dump_ = false; 2392 gflags.will_dump = false;
2393 error ("Attempt to autoload %s while preparing to dump", 2393 error ("Attempt to autoload %s while preparing to dump",
2394 SDATA (SYMBOL_NAME (funname))); 2394 SDATA (SYMBOL_NAME (funname)));
2395 } 2395 }
diff --git a/src/fns.c b/src/fns.c
index 62283e92eb7..dcbcd2aa40e 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -3780,7 +3780,7 @@ FILENAME are suppressed. */)
3780 { 3780 {
3781 /* Avoid landing here recursively while outputting the 3781 /* Avoid landing here recursively while outputting the
3782 backtrace from the error. */ 3782 backtrace from the error. */
3783 gflags.will_dump_ = false; 3783 gflags.will_dump = false;
3784 error ("(require %s) while preparing to dump", 3784 error ("(require %s) while preparing to dump",
3785 SDATA (SYMBOL_NAME (feature))); 3785 SDATA (SYMBOL_NAME (feature)));
3786 } 3786 }
diff --git a/src/lisp.h b/src/lisp.h
index 24e4fe0f84d..22c822ad12f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -89,18 +89,21 @@ DEFINE_GDB_SYMBOL_END (GCTYPEBITS)
89typedef int EMACS_INT; 89typedef int EMACS_INT;
90typedef unsigned int EMACS_UINT; 90typedef unsigned int EMACS_UINT;
91enum { EMACS_INT_WIDTH = INT_WIDTH, EMACS_UINT_WIDTH = UINT_WIDTH }; 91enum { EMACS_INT_WIDTH = INT_WIDTH, EMACS_UINT_WIDTH = UINT_WIDTH };
92# define ALIGNOF_EMACS_INT ALIGNOF_INT
92# define EMACS_INT_MAX INT_MAX 93# define EMACS_INT_MAX INT_MAX
93# define pI "" 94# define pI ""
94# elif INTPTR_MAX <= LONG_MAX && !defined WIDE_EMACS_INT 95# elif INTPTR_MAX <= LONG_MAX && !defined WIDE_EMACS_INT
95typedef long int EMACS_INT; 96typedef long int EMACS_INT;
96typedef unsigned long EMACS_UINT; 97typedef unsigned long EMACS_UINT;
97enum { EMACS_INT_WIDTH = LONG_WIDTH, EMACS_UINT_WIDTH = ULONG_WIDTH }; 98enum { EMACS_INT_WIDTH = LONG_WIDTH, EMACS_UINT_WIDTH = ULONG_WIDTH };
99# define ALIGNOF_EMACS_INT ALIGNOF_LONG
98# define EMACS_INT_MAX LONG_MAX 100# define EMACS_INT_MAX LONG_MAX
99# define pI "l" 101# define pI "l"
100# elif INTPTR_MAX <= LLONG_MAX 102# elif INTPTR_MAX <= LLONG_MAX
101typedef long long int EMACS_INT; 103typedef long long int EMACS_INT;
102typedef unsigned long long int EMACS_UINT; 104typedef unsigned long long int EMACS_UINT;
103enum { EMACS_INT_WIDTH = LLONG_WIDTH, EMACS_UINT_WIDTH = ULLONG_WIDTH }; 105enum { EMACS_INT_WIDTH = LLONG_WIDTH, EMACS_UINT_WIDTH = ULLONG_WIDTH };
106# define ALIGNOF_EMACS_INT ALIGNOF_LONG_LONG
104# define EMACS_INT_MAX LLONG_MAX 107# define EMACS_INT_MAX LLONG_MAX
105/* MinGW supports %lld only if __USE_MINGW_ANSI_STDIO is non-zero, 108/* MinGW supports %lld only if __USE_MINGW_ANSI_STDIO is non-zero,
106 which is arranged by config.h, and (for mingw.org) if GCC is 6.0 or 109 which is arranged by config.h, and (for mingw.org) if GCC is 6.0 or
@@ -237,13 +240,26 @@ DEFINE_GDB_SYMBOL_END (INTTYPEBITS)
237 expression involving VAL_MAX. */ 240 expression involving VAL_MAX. */
238#define VAL_MAX (EMACS_INT_MAX >> (GCTYPEBITS - 1)) 241#define VAL_MAX (EMACS_INT_MAX >> (GCTYPEBITS - 1))
239 242
243/* The alignment ideally required of objects subject to garbage
244 collection. (In the sense that it would be ideal for such an
245 alignment to be available to enable LSB tagging.) */
246#define IDEAL_GCALIGNMENT 8
247
240/* Whether the least-significant bits of an EMACS_INT contain the tag. 248/* Whether the least-significant bits of an EMACS_INT contain the tag.
241 On hosts where pointers-as-ints do not exceed VAL_MAX / 2, USE_LSB_TAG is: 249 On hosts where pointers-as-ints do not exceed VAL_MAX / 2, USE_LSB_TAG is:
242 a. unnecessary, because the top bits of an EMACS_INT are unused, and 250 a. unnecessary, because the top bits of an EMACS_INT are unused, and
243 b. slower, because it typically requires extra masking. 251 b. slower, because it typically requires extra masking.
244 So, USE_LSB_TAG is true only on hosts where it might be useful. */ 252 So, USE_LSB_TAG is true only on hosts where it might be useful. */
245DEFINE_GDB_SYMBOL_BEGIN (bool, USE_LSB_TAG) 253DEFINE_GDB_SYMBOL_BEGIN (bool, USE_LSB_TAG)
254#if (ALIGNOF_EMACS_INT < IDEAL_GCALIGNMENT && !defined alignas \
255 && !defined WIDE_EMACS_INT \
256 && !defined HAVE_STRUCT_ATTRIBUTE_ALIGNED \
257 && !defined __alignas_is_defined \
258 && __STDC_VERSION__ < 202311 && __cplusplus < 201103)
259#define USE_LSB_TAG 0
260#else /* EMACS_INT_WIDTH >= GCALIGNMENT || defined alignas ... */
246#define USE_LSB_TAG (VAL_MAX / 2 < INTPTR_MAX) 261#define USE_LSB_TAG (VAL_MAX / 2 < INTPTR_MAX)
262#endif /* EMACS_INT_WIDTH >= GCALIGNMENT || defined alignas ... */
247DEFINE_GDB_SYMBOL_END (USE_LSB_TAG) 263DEFINE_GDB_SYMBOL_END (USE_LSB_TAG)
248 264
249/* Mask for the value (as opposed to the type bits) of a Lisp object. */ 265/* Mask for the value (as opposed to the type bits) of a Lisp object. */
@@ -262,7 +278,7 @@ DEFINE_GDB_SYMBOL_END (VALMASK)
262 USE_LSB_TAG, 1 otherwise. It must be a literal integer constant, 278 USE_LSB_TAG, 1 otherwise. It must be a literal integer constant,
263 for older versions of GCC (through at least 4.9). */ 279 for older versions of GCC (through at least 4.9). */
264#if USE_LSB_TAG 280#if USE_LSB_TAG
265# define GCALIGNMENT 8 281# define GCALIGNMENT IDEAL_GCALIGNMENT
266# if GCALIGNMENT != 1 << GCTYPEBITS 282# if GCALIGNMENT != 1 << GCTYPEBITS
267# error "GCALIGNMENT and GCTYPEBITS are inconsistent" 283# error "GCALIGNMENT and GCTYPEBITS are inconsistent"
268# endif 284# endif
@@ -629,15 +645,15 @@ extern bool initialized;
629extern struct gflags 645extern struct gflags
630{ 646{
631 /* True means this Emacs instance was born to dump. */ 647 /* True means this Emacs instance was born to dump. */
632 bool will_dump_ : 1; 648 bool will_dump;
633 bool will_bootstrap_ : 1; 649 bool will_bootstrap;
634#ifdef HAVE_PDUMPER 650#ifdef HAVE_PDUMPER
635 /* Set in an Emacs process that will likely dump with pdumper; all 651 /* Set in an Emacs process that will likely dump with pdumper; all
636 Emacs processes may dump with pdumper, however. */ 652 Emacs processes may dump with pdumper, however. */
637 bool will_dump_with_pdumper_ : 1; 653 bool will_dump_with_pdumper;
638 /* Set in an Emacs process that has been restored from a portable 654 /* Set in an Emacs process that has been restored from a portable
639 dump. */ 655 dump. */
640 bool dumped_with_pdumper_ : 1; 656 bool dumped_with_pdumper;
641#endif 657#endif
642} gflags; 658} gflags;
643 659
@@ -645,7 +661,7 @@ INLINE bool
645will_dump_p (void) 661will_dump_p (void)
646{ 662{
647#if HAVE_PDUMPER 663#if HAVE_PDUMPER
648 return gflags.will_dump_; 664 return gflags.will_dump;
649#else 665#else
650 return false; 666 return false;
651#endif 667#endif
@@ -655,7 +671,7 @@ INLINE bool
655will_bootstrap_p (void) 671will_bootstrap_p (void)
656{ 672{
657#if HAVE_PDUMPER 673#if HAVE_PDUMPER
658 return gflags.will_bootstrap_; 674 return gflags.will_bootstrap;
659#else 675#else
660 return false; 676 return false;
661#endif 677#endif
@@ -665,7 +681,7 @@ INLINE bool
665will_dump_with_pdumper_p (void) 681will_dump_with_pdumper_p (void)
666{ 682{
667#if HAVE_PDUMPER 683#if HAVE_PDUMPER
668 return gflags.will_dump_with_pdumper_; 684 return gflags.will_dump_with_pdumper;
669#else 685#else
670 return false; 686 return false;
671#endif 687#endif
@@ -675,7 +691,7 @@ INLINE bool
675dumped_with_pdumper_p (void) 691dumped_with_pdumper_p (void)
676{ 692{
677#if HAVE_PDUMPER 693#if HAVE_PDUMPER
678 return gflags.dumped_with_pdumper_; 694 return gflags.dumped_with_pdumper;
679#else 695#else
680 return false; 696 return false;
681#endif 697#endif
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