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.
This commit is contained in:
Po Lu 2025-03-09 23:02:21 +08:00
parent 57cef07710
commit a5f8ce9f1e
8 changed files with 193 additions and 100 deletions

View file

@ -3218,8 +3218,68 @@ AC_CACHE_CHECK(
fi])
doug_lea_malloc=$emacs_cv_var_doug_lea_malloc
AC_CHECK_ALIGNOF([int])
AC_CHECK_ALIGNOF([long])
AC_CHECK_ALIGNOF([long long])
AC_CHECK_SIZEOF([long])
AC_CACHE_CHECK([for struct alignment],
[emacs_cv_struct_alignment],
[AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <stddef.h>
struct s { char c; } __attribute__ ((aligned (8)));
struct t { char c; struct s s; };
char verify[offsetof (struct t, s) == 8 ? 1 : -1];
]])],
[emacs_cv_struct_alignment=yes],
[emacs_cv_struct_alignment=no])])
if test "$emacs_cv_struct_alignment" = yes; then
AC_DEFINE([HAVE_STRUCT_ATTRIBUTE_ALIGNED], [1],
[Define to 1 if 'struct __attribute__ ((aligned (N)))' aligns the
structure to an N-byte boundary.])
fi
system_malloc=yes
# If it appears as if the system malloc can't be trusted to return
# adequately positioned memory, enable the GNU malloc, which more
# consistently provides allocations at low addresses, as is required for
# the pdumper to load dump files at a representable location.
AS_IF([test "$with_pdumper" = "yes" && test "$with_wide_int" != "yes"],
AC_CHECK_HEADERS([stdalign.h])
[AC_CACHE_CHECK([whether alignas is required yet unavailable],
[emacs_cv_alignas_unavailable],
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#ifdef HAVE_STDALIGN_H
#include <stdalign.h>
#endif
#include <limits.h>
]], [[
#define IDEAL_GCALIGNMENT 8
#if INTPTR_MAX <= INT_MAX && !defined WIDE_EMACS_INT
# define ALIGNOF_EMACS_INT ALIGNOF_INT
# elif INTPTR_MAX <= LONG_MAX && !defined WIDE_EMACS_INT
# define ALIGNOF_EMACS_INT ALIGNOF_LONG
# elif INTPTR_MAX <= LLONG_MAX
# define ALIGNOF_EMACS_INT ALIGNOF_LONG_LONG
# else
# error "INTPTR_MAX too large"
#endif
#if (ALIGNOF_EMACS_INT < IDEAL_GCALIGNMENT && !defined alignas \
&& !defined HAVE_STRUCT_ATTRIBUTE_ALIGNED \
&& !defined __alignas_is_defined \
&& __STDC_VERSION__ < 202311 && __cplusplus < 201103)
#error "!USE_LSB_TAG required"
#endif
]])], [emacs_cv_alignas_unavailable=no],
[emacs_cv_alignas_unavailable=yes])])
AS_IF([test "$emacs_cv_alignas_unavailable" = "yes"],
[system_malloc=no
AC_MSG_WARN([The GNU memory manager will be enabled as your system
does not guarantee that the portable dumper can allocate memory at a suitably
low address.])])])
dnl This must be before the test of $ac_cv_func_sbrk below.
AC_CHECK_FUNCS_ONCE([sbrk])
@ -5823,7 +5883,6 @@ AC_SUBST([HAVE_LIBSECCOMP])
AC_SUBST([LIBSECCOMP_LIBS])
AC_SUBST([LIBSECCOMP_CFLAGS])
AC_CHECK_SIZEOF([long])
SIZEOF_LONG="$ac_cv_sizeof_long"
AC_SUBST([SIZEOF_LONG])
@ -7186,22 +7245,6 @@ else
fi
AC_SUBST([LIBXMENU])
AC_CACHE_CHECK([for struct alignment],
[emacs_cv_struct_alignment],
[AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <stddef.h>
struct s { char c; } __attribute__ ((aligned (8)));
struct t { char c; struct s s; };
char verify[offsetof (struct t, s) == 8 ? 1 : -1];
]])],
[emacs_cv_struct_alignment=yes],
[emacs_cv_struct_alignment=no])])
if test "$emacs_cv_struct_alignment" = yes; then
AC_DEFINE([HAVE_STRUCT_ATTRIBUTE_ALIGNED], [1],
[Define to 1 if 'struct __attribute__ ((aligned (N)))' aligns the
structure to an N-byte boundary.])
fi
AC_C_RESTRICT
AC_C_TYPEOF

View file

@ -140,6 +140,9 @@ s/^#undef HAVE_DECL_STRTOIMAX *$/#define HAVE_DECL_STRTOIMAX 1/
s/^#undef HAVE_PDUMPER *$/#define HAVE_PDUMPER 1/
s/^#undef HAVE_STRTOLL *$/#define HAVE_STRTOLL 1/
s/^#undef HAVE_STRTOULL *$/#define HAVE_STRTOULL 1/
s/^#undef ALIGNOF_INT *$/s/^.*$/#define ALIGNOF_INT 4/
s/^#undef ALIGNOF_LONG *$/s/^.*$/#define ALIGNOF_LONG 4/
s/^#undef ALIGNOF_LONG_LONG *$/s/^.*$/#define ALIGNOF_LONG_LONG 4/
/^#undef HAVE_STRUCT_DIRENT_D_TYPE *$/c\
#if __DJGPP__ + (__DJGPP_MINOR__ >= 5) >= 3\
#define HAVE_STRUCT_DIRENT_D_TYPE 1/\

View file

@ -150,8 +150,6 @@ union emacs_align_type
{
struct frame frame;
struct Lisp_Bignum Lisp_Bignum;
struct Lisp_Bool_Vector Lisp_Bool_Vector;
struct Lisp_Char_Table Lisp_Char_Table;
struct Lisp_CondVar Lisp_CondVar;
struct Lisp_Finalizer Lisp_Finalizer;
struct Lisp_Float Lisp_Float;
@ -160,21 +158,25 @@ union emacs_align_type
struct Lisp_Misc_Ptr Lisp_Misc_Ptr;
struct Lisp_Mutex Lisp_Mutex;
struct Lisp_Overlay Lisp_Overlay;
struct Lisp_Sub_Char_Table Lisp_Sub_Char_Table;
struct Lisp_Subr Lisp_Subr;
struct Lisp_Sqlite Lisp_Sqlite;
struct Lisp_User_Ptr Lisp_User_Ptr;
struct Lisp_Vector Lisp_Vector;
struct terminal terminal;
struct thread_state thread_state;
struct window window;
/* Omit the following since they would require including process.h
etc. In practice their alignments never exceed that of the
structs already listed. */
etc, or because they are defined with flexible array members, which
are rejected by some C99 compilers when this union subsequently
appears in an `alignof' expression. In practice their alignments
never exceed that of the structs already listed. */
#if 0
struct Lisp_Bool_Vector Lisp_Bool_Vector;
struct Lisp_Char_Table Lisp_Char_Table;
struct Lisp_Sub_Char_Table Lisp_Sub_Char_Table;
struct Lisp_Module_Function Lisp_Module_Function;
struct Lisp_Process Lisp_Process;
struct Lisp_Vector Lisp_Vector;
struct save_window_data save_window_data;
struct scroll_bar scroll_bar;
struct xwidget_view xwidget_view;
@ -5167,14 +5169,20 @@ mark_memory (void const *start, void const *end)
for (pp = start; (void const *) pp < end; pp += GC_POINTER_ALIGNMENT)
{
void *p = *(void *const *) pp;
intptr_t ip;
#if !USE_LSB_TAG && !defined WIDE_EMACS_INT
ip = (intptr_t) p;
mark_maybe_pointer ((void *) (ip & VALMASK), false);
#else /* USE_LSB_TAG || WIDE_EMACS_INT */
mark_maybe_pointer (p, false);
#endif /* USE_LSB_TAG || WIDE_EMACS_INT */
/* Unmask any struct Lisp_Symbol pointer that make_lisp_symbol
previously disguised by adding the address of 'lispsym'.
On a host with 32-bit pointers and 64-bit Lisp_Objects,
a Lisp_Object might be split into registers saved into
non-adjacent words and P might be the low-order word's value. */
intptr_t ip;
ckd_add (&ip, (intptr_t) p, (intptr_t) lispsym);
mark_maybe_pointer ((void *) ip, true);
}

View file

@ -1311,13 +1311,11 @@ android_emacs_init (int argc, char **argv, char *dump_file)
if (!initialized && temacs)
{
#ifdef HAVE_PDUMPER
if (strcmp (temacs, "pdump") == 0 ||
strcmp (temacs, "pbootstrap") == 0)
gflags.will_dump_with_pdumper_ = true;
if (strcmp (temacs, "pbootstrap") == 0)
gflags.will_bootstrap_ = true;
gflags.will_dump_ =
will_dump_with_pdumper_p ();
if (!strcmp (temacs, "pdump") || !strcmp (temacs, "pbootstrap"))
gflags.will_dump_with_pdumper = true;
if (!strcmp (temacs, "pbootstrap"))
gflags.will_bootstrap = true;
gflags.will_dump = will_dump_with_pdumper_p ();
if (will_dump_p ())
dump_mode = temacs;
#endif

View file

@ -2389,7 +2389,7 @@ it defines a macro. */)
{
/* Avoid landing here recursively while outputting the
backtrace from the error. */
gflags.will_dump_ = false;
gflags.will_dump = false;
error ("Attempt to autoload %s while preparing to dump",
SDATA (SYMBOL_NAME (funname)));
}

View file

@ -3780,7 +3780,7 @@ FILENAME are suppressed. */)
{
/* Avoid landing here recursively while outputting the
backtrace from the error. */
gflags.will_dump_ = false;
gflags.will_dump = false;
error ("(require %s) while preparing to dump",
SDATA (SYMBOL_NAME (feature)));
}

View file

@ -89,18 +89,21 @@ DEFINE_GDB_SYMBOL_END (GCTYPEBITS)
typedef int EMACS_INT;
typedef unsigned int EMACS_UINT;
enum { EMACS_INT_WIDTH = INT_WIDTH, EMACS_UINT_WIDTH = UINT_WIDTH };
# define ALIGNOF_EMACS_INT ALIGNOF_INT
# define EMACS_INT_MAX INT_MAX
# define pI ""
# elif INTPTR_MAX <= LONG_MAX && !defined WIDE_EMACS_INT
typedef long int EMACS_INT;
typedef unsigned long EMACS_UINT;
enum { EMACS_INT_WIDTH = LONG_WIDTH, EMACS_UINT_WIDTH = ULONG_WIDTH };
# define ALIGNOF_EMACS_INT ALIGNOF_LONG
# define EMACS_INT_MAX LONG_MAX
# define pI "l"
# elif INTPTR_MAX <= LLONG_MAX
typedef long long int EMACS_INT;
typedef unsigned long long int EMACS_UINT;
enum { EMACS_INT_WIDTH = LLONG_WIDTH, EMACS_UINT_WIDTH = ULLONG_WIDTH };
# define ALIGNOF_EMACS_INT ALIGNOF_LONG_LONG
# define EMACS_INT_MAX LLONG_MAX
/* MinGW supports %lld only if __USE_MINGW_ANSI_STDIO is non-zero,
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)
expression involving VAL_MAX. */
#define VAL_MAX (EMACS_INT_MAX >> (GCTYPEBITS - 1))
/* The alignment ideally required of objects subject to garbage
collection. (In the sense that it would be ideal for such an
alignment to be available to enable LSB tagging.) */
#define IDEAL_GCALIGNMENT 8
/* Whether the least-significant bits of an EMACS_INT contain the tag.
On hosts where pointers-as-ints do not exceed VAL_MAX / 2, USE_LSB_TAG is:
a. unnecessary, because the top bits of an EMACS_INT are unused, and
b. slower, because it typically requires extra masking.
So, USE_LSB_TAG is true only on hosts where it might be useful. */
DEFINE_GDB_SYMBOL_BEGIN (bool, USE_LSB_TAG)
#if (ALIGNOF_EMACS_INT < IDEAL_GCALIGNMENT && !defined alignas \
&& !defined WIDE_EMACS_INT \
&& !defined HAVE_STRUCT_ATTRIBUTE_ALIGNED \
&& !defined __alignas_is_defined \
&& __STDC_VERSION__ < 202311 && __cplusplus < 201103)
#define USE_LSB_TAG 0
#else /* EMACS_INT_WIDTH >= GCALIGNMENT || defined alignas ... */
#define USE_LSB_TAG (VAL_MAX / 2 < INTPTR_MAX)
#endif /* EMACS_INT_WIDTH >= GCALIGNMENT || defined alignas ... */
DEFINE_GDB_SYMBOL_END (USE_LSB_TAG)
/* Mask for the value (as opposed to the type bits) of a Lisp object. */
@ -262,7 +278,7 @@ DEFINE_GDB_SYMBOL_END (VALMASK)
USE_LSB_TAG, 1 otherwise. It must be a literal integer constant,
for older versions of GCC (through at least 4.9). */
#if USE_LSB_TAG
# define GCALIGNMENT 8
# define GCALIGNMENT IDEAL_GCALIGNMENT
# if GCALIGNMENT != 1 << GCTYPEBITS
# error "GCALIGNMENT and GCTYPEBITS are inconsistent"
# endif
@ -629,15 +645,15 @@ extern bool initialized;
extern struct gflags
{
/* True means this Emacs instance was born to dump. */
bool will_dump_ : 1;
bool will_bootstrap_ : 1;
bool will_dump;
bool will_bootstrap;
#ifdef HAVE_PDUMPER
/* Set in an Emacs process that will likely dump with pdumper; all
Emacs processes may dump with pdumper, however. */
bool will_dump_with_pdumper_ : 1;
bool will_dump_with_pdumper;
/* Set in an Emacs process that has been restored from a portable
dump. */
bool dumped_with_pdumper_ : 1;
bool dumped_with_pdumper;
#endif
} gflags;
@ -645,7 +661,7 @@ INLINE bool
will_dump_p (void)
{
#if HAVE_PDUMPER
return gflags.will_dump_;
return gflags.will_dump;
#else
return false;
#endif
@ -655,7 +671,7 @@ INLINE bool
will_bootstrap_p (void)
{
#if HAVE_PDUMPER
return gflags.will_bootstrap_;
return gflags.will_bootstrap;
#else
return false;
#endif
@ -665,7 +681,7 @@ INLINE bool
will_dump_with_pdumper_p (void)
{
#if HAVE_PDUMPER
return gflags.will_dump_with_pdumper_;
return gflags.will_dump_with_pdumper;
#else
return false;
#endif
@ -675,7 +691,7 @@ INLINE bool
dumped_with_pdumper_p (void)
{
#if HAVE_PDUMPER
return gflags.dumped_with_pdumper_;
return gflags.dumped_with_pdumper;
#else
return false;
#endif

View file

@ -77,7 +77,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#define VM_POSIX 1
#define VM_MS_WINDOWS 2
#if defined (HAVE_MMAP) && defined (MAP_FIXED)
#if !USE_LSB_TAG
# define VM_SUPPORTED 0
#elif defined (HAVE_MMAP) && defined (MAP_FIXED)
# define VM_SUPPORTED VM_POSIX
# if !defined (MAP_POPULATE) && defined (MAP_PREFAULT_READ)
# define MAP_POPULATE MAP_PREFAULT_READ
@ -1964,9 +1966,9 @@ dump_field_emacs_ptr (struct dump_context *ctx,
}
static void
_dump_object_start_pseudovector (struct dump_context *ctx,
union vectorlike_header *out_hdr,
const union vectorlike_header *in_hdr)
dump_object_start_pseudovector (struct dump_context *ctx,
union vectorlike_header *out_hdr,
const union vectorlike_header *in_hdr)
{
eassert (in_hdr->size & PSEUDOVECTOR_FLAG);
ptrdiff_t vec_size = vectorlike_nbytes (in_hdr);
@ -1976,9 +1978,9 @@ _dump_object_start_pseudovector (struct dump_context *ctx,
/* Need a macro for alloca. */
#define START_DUMP_PVEC(ctx, hdr, type, out) \
const union vectorlike_header *_in_hdr = (hdr); \
type *out = alloca (vectorlike_nbytes (_in_hdr)); \
_dump_object_start_pseudovector (ctx, &out->header, _in_hdr)
const union vectorlike_header *in_hdr = (hdr); \
type *out = alloca (vectorlike_nbytes (in_hdr)); \
dump_object_start_pseudovector (ctx, &out->header, in_hdr)
static dump_off
finish_dump_pvec (struct dump_context *ctx,
@ -3994,14 +3996,14 @@ dump_do_fixup (struct dump_context *ctx,
Lisp_Object fixup,
Lisp_Object prev_fixup)
{
enum dump_fixup_type type =
(enum dump_fixup_type) XFIXNUM (dump_pop (&fixup));
enum dump_fixup_type type
= (enum dump_fixup_type) XFIXNUM (dump_pop (&fixup));
dump_off dump_fixup_offset = dump_off_from_lisp (dump_pop (&fixup));
#ifdef ENABLE_CHECKING
if (!NILP (prev_fixup))
{
dump_off prev_dump_fixup_offset =
dump_off_from_lisp (XCAR (XCDR (prev_fixup)));
dump_off prev_dump_fixup_offset
= dump_off_from_lisp (XCAR (XCDR (prev_fixup)));
eassert (dump_fixup_offset - prev_dump_fixup_offset
>= sizeof (void *));
}
@ -4618,23 +4620,8 @@ dump_anonymous_allocate_posix (void *base,
}
#endif
/* Perform anonymous memory allocation. */
static void *
dump_anonymous_allocate (void *base,
const size_t size,
enum dump_memory_protection protection)
{
#if VM_SUPPORTED == VM_POSIX
return dump_anonymous_allocate_posix (base, size, protection);
#elif VM_SUPPORTED == VM_MS_WINDOWS
return dump_anonymous_allocate_w32 (base, size, protection);
#else
errno = ENOSYS;
return NULL;
#endif
}
/* Undo the effect of `dump_reserve_address_space'. */
/* Undo the effect of dump_reserve_address_space(). */
static void
dump_anonymous_release (void *addr, size_t size)
{
@ -4653,6 +4640,26 @@ dump_anonymous_release (void *addr, size_t size)
#endif
}
/* Perform anonymous memory allocation. */
static void *
dump_anonymous_allocate (void *base,
const size_t size,
enum dump_memory_protection protection)
{
void *val;
#if VM_SUPPORTED == VM_POSIX
val = dump_anonymous_allocate_posix (base, size, protection);
#elif VM_SUPPORTED == VM_MS_WINDOWS
val = dump_anonymous_allocate_w32 (base, size, protection);
#else
errno = ENOSYS;
val = NULL;
#endif
return val;
}
#if VM_SUPPORTED == VM_MS_WINDOWS
static void *
dump_map_file_w32 (void *base, int fd, off_t offset, size_t size,
@ -4824,20 +4831,20 @@ static void
dump_discard_mem (void *mem, size_t size)
{
#if VM_SUPPORTED == VM_MS_WINDOWS
/* Discard COWed pages. */
(void) VirtualFree (mem, size, MEM_DECOMMIT);
/* Release the commit charge for the mapping. */
DWORD old_prot;
(void) VirtualProtect (mem, size, PAGE_NOACCESS, &old_prot);
/* Discard COWed pages. */
(void) VirtualFree (mem, size, MEM_DECOMMIT);
/* Release the commit charge for the mapping. */
DWORD old_prot;
(void) VirtualProtect (mem, size, PAGE_NOACCESS, &old_prot);
#elif VM_SUPPORTED == VM_POSIX
# ifdef HAVE_POSIX_MADVISE
/* Discard COWed pages. */
(void) posix_madvise (mem, size, POSIX_MADV_DONTNEED);
/* Discard COWed pages. */
(void) posix_madvise (mem, size, POSIX_MADV_DONTNEED);
# elif defined HAVE_MADVISE
(void) madvise (mem, size, MADV_DONTNEED);
(void) madvise (mem, size, MADV_DONTNEED);
#endif
/* Release the commit charge for the mapping. */
(void) mprotect (mem, size, PROT_NONE);
/* Release the commit charge for the mapping. */
(void) mprotect (mem, size, PROT_NONE);
#endif
}
@ -4959,21 +4966,23 @@ dump_mmap_release_vm (struct dump_memory_map *map)
static bool
needs_mmap_retry_p (void)
{
#if defined CYGWIN || VM_SUPPORTED == VM_MS_WINDOWS || defined _AIX
#if defined CYGWIN || VM_SUPPORTED == VM_MS_WINDOWS \
|| defined _AIX
return true;
#else
#else /* !CYGWIN && VM_SUPPORTED != VM_MS_WINDOWS && !_AIX */
return false;
#endif
#endif /* !CYGWIN && VM_SUPPORTED != VM_MS_WINDOWS && !_AIX */
}
static bool
dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps,
size_t total_size)
{
int save_errno;
bool ret = false;
void *resv = NULL;
bool retry = false;
const bool need_retry = needs_mmap_retry_p ();
bool need_retry = needs_mmap_retry_p ();
do
{
@ -4986,11 +4995,10 @@ dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps,
}
eassert (resv == NULL);
resv = dump_anonymous_allocate (NULL,
total_size,
resv = dump_anonymous_allocate (NULL, total_size,
DUMP_MEMORY_ACCESS_NONE);
if (!resv)
goto out;
goto out;
char *mem = resv;
@ -5039,6 +5047,7 @@ dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps,
ret = true;
resv = NULL;
out:
save_errno = errno;
if (resv)
dump_anonymous_release (resv, total_size);
if (!ret)
@ -5051,6 +5060,7 @@ dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps,
dump_mmap_release (&maps[i]);
}
}
errno = save_errno;
return ret;
}
@ -5058,8 +5068,8 @@ dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps,
Each dump_memory_map structure describes how to fill the
corresponding range of memory. On input, all members except MAPPING
are valid. On output, MAPPING contains the location of the given
chunk of memory. The MAPPING for MAPS[N] is MAPS[N-1].mapping +
are valid. On output, MAPPING contains the location of the given
chunk of memory. The MAPPING for MAPS[N] is MAPS[N-1].mapping +
MAPS[N-1].size.
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)
total_size += maps[i].spec.size;
}
return (VM_SUPPORTED ? dump_mmap_contiguous_vm : dump_mmap_contiguous_heap)
(maps, nr_maps, total_size);
if (VM_SUPPORTED)
return dump_mmap_contiguous_vm (maps, nr_maps, total_size);
else
return dump_mmap_contiguous_heap (maps, nr_maps, total_size);
}
typedef uint_fast32_t dump_bitset_word;
@ -5129,7 +5141,7 @@ dump_bitset_bit_set_p (const struct dump_bitset *bitset,
{
dump_bitset_word bit = 1;
bit <<= bit_number % DUMP_BITSET_WORD_WIDTH;
return *dump_bitset__bit_slot (bitset, bit_number) & bit;
return (*dump_bitset__bit_slot (bitset, bit_number) & bit) != 0;
}
static void
@ -5548,8 +5560,8 @@ dump_do_dump_relocation (const uintptr_t dump_base,
struct bignum_reload_info reload_info;
static_assert (sizeof (reload_info) <= sizeof (*bignum_val (bignum)));
memcpy (&reload_info, bignum_val (bignum), sizeof (reload_info));
const mp_limb_t *limbs =
dump_ptr (dump_base, reload_info.data_location);
const mp_limb_t *limbs = dump_ptr (dump_base,
reload_info.data_location);
mpz_roinit_n (bignum->value, limbs, reload_info.nlimbs);
break;
}
@ -5790,15 +5802,29 @@ pdumper_load (const char *dump_filename, char *argv0)
goto out;
err = PDUMPER_LOAD_ERROR;
mark_bits_needed =
divide_round_up (header->discardable_start, DUMP_ALIGNMENT);
dump_base = (uintptr_t) sections[DS_HOT].mapping;
#if !USE_LSB_TAG
/* The dump may have been mapped at a location that does not admit of
representation as Lisp_Objects. Abort in this case. */
if ((dump_base + dump_size) & ~VALMASK)
{
fprintf (stderr,
"Failed to load dump file: 0x%p+0x%p & 0x%p != 0\n",
(void *) dump_base, (void *) dump_size,
(void *) (uintptr_t) VALMASK);
goto out;
}
#endif /* !USE_LSB_TAG */
mark_bits_needed
= divide_round_up (header->discardable_start, DUMP_ALIGNMENT);
if (!dump_bitsets_init (mark_bits, mark_bits_needed))
goto out;
/* Point of no return. */
err = PDUMPER_LOAD_SUCCESS;
dump_base = (uintptr_t) sections[DS_HOT].mapping;
gflags.dumped_with_pdumper_ = true;
gflags.dumped_with_pdumper = true;
dump_private.header = *header;
dump_private.mark_bits = mark_bits[0];
dump_private.last_mark_bits = mark_bits[1];
@ -5815,8 +5841,8 @@ pdumper_load (const char *dump_filename, char *argv0)
Lisp_Object hashes = zero_vector;
if (header->hash_list)
{
struct Lisp_Vector *hash_tables =
(struct Lisp_Vector *) (dump_base + header->hash_list);
struct Lisp_Vector *hash_tables
= (struct Lisp_Vector *) (dump_base + header->hash_list);
hashes = make_lisp_ptr (hash_tables, Lisp_Vectorlike);
}
@ -5852,7 +5878,6 @@ pdumper_load (const char *dump_filename, char *argv0)
dump_mmap_release (&sections[i]);
if (dump_fd >= 0)
emacs_close (dump_fd);
return err;
}