From d0eeae6232582b1521b780c5eb6e99b436d0e89a Mon Sep 17 00:00:00 2001 From: Pip Cet Date: Tue, 20 Aug 2024 18:31:05 +0000 Subject: [PATCH] Unexec removal: Main part * configure.ac: Remove unexec-specific parts. (EMACS_CONFIG_FEATURES): Always report that we do not have the UNEXEC feature. (AC_ECHO): No longer display a line about the unexec feature. * lisp/loadup.el: * lisp/startup.el: Remove unexec-specific code. * src/Makefile.in (base_obj): Drop 'UNEXEC_OBJ'. * src/alloc.c (staticvec): Never initialize this variable. (BLOCK_ALIGN): Always allow large blocks. (mmap_lisp_allowed_p): Remove unexec-specific code. * src/buffer.c (init_buffer): * src/conf_post.h (ADDRESS_SANITIZER): * src/emacs.c (load_pdump, main): Remove unexec-specific code. (Fdump_emacs): Remove function. (syms_of_emacs): Remove 'Fdump_emacs'. * src/lastfile.c: Remove unexec-specific code. * src/lisp.h (gflags): Remove unexec-specific flags. (will_dump_p, will_bootstrap_p, will_dump_with_unexec_p) (dumped_with_unexec_p, definitely_will_not_unexec_p): Remove or adjust predicates. (SUBR_SECTION_ATTRIBUTE): Remove unexec-specific definition. * src/pdumper.c (Fdump_emacs_portable): Remove unexec-specific warning. * src/process.c (init_process_emacs): Remove !unexec condition * src/sysdep.c (maybe_disable_address_randomization): Adjust comment. (init_signals): * src/timefns.c (init_timefns): Remove unexec-specific code. * src/w32heap.c (report_temacs_memory_usage): Remove function. * src/w32heap.h: Adjust comment. * src/w32image.c (globals_of_w32image): Remove unexec-specific code. (cherry picked from commit 15e2b14f03796467fab8e8086d293a5813afaa5b) --- configure.ac | 246 +----------------------------------------------- lisp/loadup.el | 6 +- lisp/startup.el | 4 +- src/Makefile.in | 8 +- src/alloc.c | 22 +---- src/buffer.c | 41 -------- src/conf_post.h | 25 +++++ src/emacs.c | 169 +-------------------------------- src/lastfile.c | 11 --- src/lisp.h | 100 +------------------- src/pdumper.c | 6 -- src/process.c | 67 ++++++------- src/sysdep.c | 10 +- src/timefns.c | 29 ------ src/w32heap.c | 25 ----- src/w32heap.h | 4 +- src/w32image.c | 2 - 17 files changed, 81 insertions(+), 694 deletions(-) diff --git a/configure.ac b/configure.ac index 40a33a8c31f..ac0ac8eda3c 100644 --- a/configure.ac +++ b/configure.ac @@ -444,28 +444,13 @@ this option's value should be 'yes' or 'no'.]) ;; ], [with_pdumper=auto]) -AC_ARG_WITH([unexec], - AS_HELP_STRING( - [--with-unexec=VALUE], - [enable unexec support unconditionally - ('yes', 'no', or 'auto': default 'auto')]), - [ case "${withval}" in - yes|no|auto) val=$withval ;; - *) AC_MSG_ERROR( - ['--with-unexec=$withval' is invalid; -this option's value should be 'yes' or 'no'.]) ;; - esac - with_unexec=$val - ], - [with_unexec=auto]) - AC_ARG_WITH([dumping],[AS_HELP_STRING([--with-dumping=VALUE], [kind of dumping to use for initial Emacs build -(VALUE one of: pdumper, unexec, none; default pdumper)])], +(VALUE one of: pdumper, none; default pdumper)])], [ case "${withval}" in - pdumper|unexec|none) val=$withval ;; + pdumper|none) val=$withval ;; *) AC_MSG_ERROR(['--with-dumping=$withval is invalid; -this option's value should be 'pdumper', 'unexec', or 'none'.]) +this option's value should be 'pdumper' or 'none'.]) ;; esac with_dumping=$val @@ -480,22 +465,10 @@ if test "$with_pdumper" = "auto"; then fi fi -if test "$with_unexec" = "auto"; then - if test "$with_dumping" = "unexec"; then - with_unexec=yes - else - with_unexec=no - fi -fi - if test "$with_dumping" = "pdumper" && test "$with_pdumper" = "no"; then AC_MSG_ERROR(['--with-dumping=pdumper' requires pdumper support]) fi -if test "$with_dumping" = "unexec" && test "$with_unexec" = "no"; then - AC_MSG_ERROR(['--with-dumping=unexec' requires unexec support]) -fi - if test "$with_pdumper" = "yes"; then AC_DEFINE([HAVE_PDUMPER], [1], [Define to build with portable dumper support]) @@ -2070,10 +2043,6 @@ AC_PATH_PROG([GZIP_PROG], [gzip]) test $with_compress_install != yes && test -n "$GZIP_PROG" && \ GZIP_PROG=" # $GZIP_PROG # (disabled by configure --without-compress-install)" -if test "$with_dumping" = "unexec" && test "$opsys" = "nacl"; then - AC_MSG_ERROR([nacl is not compatible with --with-dumping=unexec]) -fi - AC_CACHE_CHECK([for 'find' args to delete a file], [emacs_cv_find_delete], [if touch conftest.tmp && find conftest.tmp -delete 2>/dev/null && @@ -2088,48 +2057,6 @@ AC_SUBST([FIND_DELETE]) PAXCTL_dumped= PAXCTL_notdumped= -if test $with_unexec = yes && test $opsys = gnu-linux; then - if test "${SETFATTR+set}" != set; then - AC_CACHE_CHECK([for setfattr], - [emacs_cv_prog_setfattr], - [touch conftest.tmp - if (setfattr -n user.pax.flags conftest.tmp) >/dev/null 2>&1; then - emacs_cv_prog_setfattr=yes - else - emacs_cv_prog_setfattr=no - fi]) - if test "$emacs_cv_prog_setfattr" = yes; then - PAXCTL_notdumped='$(SETFATTR) -n user.pax.flags -v er' - SETFATTR=setfattr - else - SETFATTR= - fi - fi - case $opsys,$PAXCTL_notdumped,$emacs_uname_r in - gnu-linux,,* | netbsd,,[0-7].*) - AC_PATH_PROG([PAXCTL], [paxctl], [], - [$PATH$PATH_SEPARATOR/sbin$PATH_SEPARATOR/usr/sbin]) - if test -n "$PAXCTL"; then - if test "$opsys" = netbsd; then - PAXCTL_dumped='$(PAXCTL) +a' - PAXCTL_notdumped=$PAXCTL_dumped - else - AC_MSG_CHECKING([whether binaries have a PT_PAX_FLAGS header]) - AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], - [if $PAXCTL -v conftest$EXEEXT >/dev/null 2>&1; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - PAXCTL= - fi]) - if test -n "$PAXCTL"; then - PAXCTL_dumped='$(PAXCTL) -zex' - PAXCTL_notdumped='$(PAXCTL) -r' - fi - fi - fi;; - esac -fi AC_SUBST([PAXCTL_dumped]) AC_SUBST([PAXCTL_notdumped]) AC_SUBST([SETFATTR]) @@ -2196,37 +2123,6 @@ else ac_link="$ac_link $NON_GCC_LINK_TEST_OPTIONS" fi -dnl On some platforms using GNU ld, linking temacs needs -znocombreloc. -dnl Although this has something to do with dumping, the details are unknown. -dnl If the flag is used but not needed, -dnl Emacs should still work (albeit a bit more slowly), -dnl so use the flag everywhere that it is supported. -dnl When testing whether the flag works, treat GCC specially -dnl since it just gives a non-fatal 'unrecognized option' -dnl if not built to support GNU ld. -if test "$GCC" = yes; then - LDFLAGS_NOCOMBRELOC="-Wl,-znocombreloc" -else - LDFLAGS_NOCOMBRELOC="-znocombreloc" -fi - -AC_CACHE_CHECK([for -znocombreloc], [emacs_cv_znocombreloc], - [if test $with_unexec = no; then - emacs_cv_znocombreloc='not needed' - else - save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS $LDFLAGS_NOCOMBRELOC" - AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], - [emacs_cv_znocombreloc=yes], [emacs_cv_znocombreloc=no]) - LDFLAGS=$save_LDFLAGS - fi]) - -case $emacs_cv_znocombreloc in - no*) - LDFLAGS_NOCOMBRELOC= ;; -esac - - AC_CACHE_CHECK([whether addresses are sanitized], [emacs_cv_sanitize_address], [AC_COMPILE_IFELSE( @@ -2242,48 +2138,8 @@ AC_CACHE_CHECK([whether addresses are sanitized], [emacs_cv_sanitize_address=yes], [emacs_cv_sanitize_address=no])]) -if test $with_unexec = yes; then - AC_DEFINE([HAVE_UNEXEC], [1], [Define if Emacs supports unexec.]) - if test "$emacs_cv_sanitize_address" = yes; then - AC_MSG_WARN([[Addresses are sanitized; suggest --without-unexec]]) - fi -fi - - -UNEXEC_OBJ= -test $with_unexec = yes && -case "$opsys" in - # MSDOS uses unexcoff.o - aix4-2) - UNEXEC_OBJ=unexaix.o - ;; - cygwin) - UNEXEC_OBJ=unexcw.o - ;; - darwin) - UNEXEC_OBJ=unexmacosx.o - ;; - hpux10-20 | hpux11) - UNEXEC_OBJ=unexhp9k800.o - ;; - mingw32) - UNEXEC_OBJ=unexw32.o - ;; - solaris) - # Use the Solaris dldump() function, called from unexsol.c, to dump - # emacs, instead of the generic ELF dump code found in unexelf.c. - # The resulting binary has a complete symbol table, and is better - # for debugging and other observability tools (debuggers, pstack, etc). - UNEXEC_OBJ=unexsol.o - ;; - *) - UNEXEC_OBJ=unexelf.o - ;; -esac -AC_SUBST([UNEXEC_OBJ]) - LD_SWITCH_SYSTEM= -test "$with_unexec" = no || case "$opsys" in +case "$opsys" in freebsd|dragonfly) ## Let 'ld' find image libs and similar things in /usr/local/lib. ## The system compiler, GCC, has apparently been modified to not @@ -2331,22 +2187,6 @@ esac C_SWITCH_MACHINE= -test $with_unexec = yes && -case $canonical in - alpha*) - ## With ELF, make sure that all common symbols get allocated to in the - ## data section. Otherwise, the dump of temacs may miss variables in - ## the shared library that have been initialized. For example, with - ## GNU libc, __malloc_initialized would normally be resolved to the - ## shared library's .bss section, which is fatal. - if test "x$GCC" = "xyes"; then - C_SWITCH_MACHINE="-fno-common" - else - AC_MSG_ERROR([Non-GCC compilers are not supported.]) - fi - ;; -esac - AC_CACHE_CHECK([for flags to work around GCC bug 58416], [emacs_cv_gcc_bug_58416_CFLAGS], [emacs_cv_gcc_bug_58416_CFLAGS='none needed' @@ -3379,21 +3219,6 @@ system_malloc=yes dnl This must be before the test of $ac_cv_func_sbrk below. AC_CHECK_FUNCS_ONCE([sbrk]) -test $with_unexec = yes && -case "$opsys" in - ## darwin ld insists on the use of malloc routines in the System framework. - darwin | mingw32 | nacl | solaris) ;; - cygwin | qnxnto | freebsd) - hybrid_malloc=yes - system_malloc= ;; - *) test "$ac_cv_func_sbrk" = yes && system_malloc=$emacs_cv_sanitize_address;; -esac - -if test "${system_malloc}" != yes && test "${doug_lea_malloc}" != yes \ - && test "${UNEXEC_OBJ}" = unexelf.o; then - hybrid_malloc=yes -fi - GMALLOC_OBJ= HYBRID_MALLOC= if test "${system_malloc}" = "yes"; then @@ -5317,15 +5142,9 @@ if test "${with_native_compilation}" = "default"; then # Check if libgccjit really works. AC_RUN_IFELSE([libgccjit_smoke_test], [], [libgccjit_broken]) fi - if test "$with_unexec" = yes; then - with_native_compilation=no - fi fi if test "${with_native_compilation}" != "no"; then - if test "$with_unexec" = yes; then - AC_MSG_ERROR(['--with-native-compilation' is not compatible with unexec]) - fi if test "${HAVE_ZLIB}" = no; then AC_MSG_ERROR(['--with-native-compilation' requires zlib]) fi @@ -6139,19 +5958,6 @@ dnl No need to check for posix_memalign if aligned_alloc works. AC_CHECK_FUNCS([aligned_alloc posix_memalign], [break]) AC_CHECK_DECLS([aligned_alloc], [], [], [[#include ]]) -case $with_unexec,$canonical in - yes,alpha*) - AC_CHECK_DECL([__ELF__], [], - [AC_MSG_ERROR([Non-ELF systems are not supported on this platform.])]);; -esac - -if test "$with_unexec" = yes && test "$opsys" = "haiku"; then - dnl A serious attempt was actually made to port unexec to Haiku. - dnl Something in libstdc++ seems to prevent it from working. - AC_MSG_ERROR([Haiku is not supported by the legacy unexec dumper. -Please use the portable dumper instead.]) -fi - # Dump loading. Android lacks posix_madvise. AC_CHECK_FUNCS([posix_madvise madvise]) @@ -7597,9 +7403,6 @@ case "$opsys" in ## about 14 to about 34. Setting it high gets us plenty of slop and ## only costs about 1.5K of wasted binary space. headerpad_extra=1000 - if test "$with_unexec" = yes; then - LD_SWITCH_SYSTEM_TEMACS="-fno-pie $LD_SWITCH_SYSTEM_TEMACS -Xlinker -headerpad -Xlinker $headerpad_extra" - fi ## This is here because src/Makefile.in did some extra fiddling around ## with LD_SWITCH_SYSTEM. It seems cleaner to put this in @@ -7625,49 +7428,11 @@ case "$opsys" in x86_64-*-*) LD_SWITCH_SYSTEM_TEMACS="-Wl,-stack,0x00800000 -Wl,-heap,0x00100000 -Wl,-image-base,0x400000000 -Wl,-entry,__start -Wl,-Map,./temacs.map" ;; *) LD_SWITCH_SYSTEM_TEMACS="-Wl,-stack,0x00800000 -Wl,-heap,0x00100000 -Wl,-image-base,0x01000000 -Wl,-entry,__start -Wl,-Map,./temacs.map" ;; esac - ## If they want unexec, disable Windows ASLR for the Emacs binary - if test "$with_dumping" = "unexec"; then - case "$canonical" in - x86_64-*-*) LD_SWITCH_SYSTEM_TEMACS="$LD_SWITCH_SYSTEM_TEMACS -Wl,-disable-dynamicbase -Wl,-disable-high-entropy-va -Wl,-default-image-base-low" ;; - *) LD_SWITCH_SYSTEM_TEMACS="$LD_SWITCH_SYSTEM_TEMACS -Wl,-disable-dynamicbase" ;; - esac - fi ;; *) LD_SWITCH_SYSTEM_TEMACS= ;; esac -# -no-pie or -nopie fixes a temacs segfault on Gentoo, OpenBSD, -# Ubuntu, and other systems with "hardened" GCC configurations for -# some reason (Bug#18784). We don't know why this works, but not -# segfaulting is better than segfaulting. Use ac_c_werror_flag=yes -# when trying the option, otherwise clang keeps warning that it does -# not understand it, and pre-4.6 GCC has a similar problem -# (Bug#20338). Prefer -no-pie to -nopie, as -no-pie is the -# spelling used by GCC 6.1.0 and later (Bug#24682). -AC_CACHE_CHECK( - [for $CC option to disable position independent executables], - [emacs_cv_prog_cc_no_pie], - [if test $with_unexec = no; then - emacs_cv_prog_cc_no_pie='not needed' - else - emacs_save_c_werror_flag=$ac_c_werror_flag - emacs_save_LDFLAGS=$LDFLAGS - ac_c_werror_flag=yes - for emacs_cv_prog_cc_no_pie in -no-pie -nopie no; do - test $emacs_cv_prog_cc_no_pie = no && break - LDFLAGS="$emacs_save_LDFLAGS $emacs_cv_prog_cc_no_pie" - AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [break]) - done - ac_c_werror_flag=$emacs_save_c_werror_flag - LDFLAGS=$emacs_save_LDFLAGS - fi]) -case $emacs_cv_prog_cc_no_pie in - -*) - LD_SWITCH_SYSTEM_TEMACS="$LD_SWITCH_SYSTEM_TEMACS $emacs_cv_prog_cc_no_pie" - ;; -esac - if test x$ac_enable_profiling != x ; then case $opsys in *freebsd | gnu-linux) ;; @@ -7781,7 +7546,7 @@ for opt in ACL BE_APP CAIRO DBUS FREETYPE GCONF GIF GLIB GMP GNUTLS GPM GSETTING case $opt in PDUMPER) val=${with_pdumper} ;; - UNEXEC) val=${with_unexec} ;; + UNEXEC) val=no ;; GLIB) val=${emacs_cv_links_glib} ;; NOTIFY|ACL) eval val=\${${opt}_SUMMARY} ;; TOOLKIT_SCROLL_BARS|X_TOOLKIT) eval val=\${USE_$opt} ;; @@ -7857,7 +7622,6 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D Does Emacs support Xwidgets? ${HAVE_XWIDGETS} Does Emacs have threading support in lisp? ${threads_enabled} Does Emacs support the portable dumper? ${with_pdumper} - Does Emacs support legacy unexec dumping? ${with_unexec} Which dumping strategy does Emacs use? ${with_dumping} Does Emacs have native lisp compiler? ${HAVE_NATIVE_COMP} Does Emacs use version 2 of the X Input Extension? ${HAVE_XINPUT2} diff --git a/lisp/loadup.el b/lisp/loadup.el index 9aac17b2c30..c6b20697a3a 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el @@ -57,7 +57,7 @@ ;; Add subdirectories to the load-path for files that might get ;; autoloaded when bootstrapping or running Emacs normally. ;; This is because PATH_DUMPLOADSEARCH is just "../lisp". -(if (or (member dump-mode '("bootstrap" "pbootstrap")) +(if (or (member dump-mode '("pbootstrap")) ;; FIXME this is irritatingly fragile. (and (stringp (nth 4 command-line-args)) (string-match "^unidata-gen\\(\\.elc?\\)?$" @@ -635,8 +635,6 @@ directory got moved. This is set to be a pair in the form of: (error nil)))))) (if dump-mode (let ((output (cond ((equal dump-mode "pdump") "emacs.pdmp") - ((equal dump-mode "dump") "emacs") - ((equal dump-mode "bootstrap") "emacs") ((equal dump-mode "pbootstrap") "bootstrap-emacs.pdmp") (t (error "Unrecognized dump mode %s" dump-mode))))) (when (and (featurep 'native-compile) @@ -680,7 +678,7 @@ directory got moved. This is set to be a pair in the form of: (eq system-type 'android)) ;; Don't bother adding another name if we're just ;; building bootstrap-emacs. - (member dump-mode '("pbootstrap" "bootstrap")))) + (member dump-mode '("pbootstrap")))) (let ((name (format "emacs-%s.%d" emacs-version emacs-build-number)) (exe (if (eq system-type 'windows-nt) ".exe" ""))) (while (string-match "[^-+_.a-zA-Z0-9]+" name) diff --git a/lisp/startup.el b/lisp/startup.el index ebd6aade1b6..a55ff6e89e6 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -1107,7 +1107,7 @@ init-file, or to a default value if loading is not possible." ;; Else, perhaps the user init file was compiled (when (and (equal (file-name-extension user-init-file) "eln") ;; The next test is for builds without native - ;; compilation support or builds with unexec. + ;; compilation support. (boundp 'comp-eln-to-el-h)) (if-let (source (gethash (file-name-nondirectory user-init-file) @@ -2526,7 +2526,7 @@ A fancy display is used on graphic displays, normal otherwise." (defalias 'about-emacs #'display-about-screen) (defalias 'display-splash-screen #'display-startup-screen) -;; This avoids byte-compiler warning in the unexec build. +;; This avoids byte-compiler warning in non-pdumper builds. (declare-function pdumper-stats "pdumper.c" ()) (defun command-line-1 (args-left) diff --git a/src/Makefile.in b/src/Makefile.in index d987124d29d..12476cede81 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -387,8 +387,6 @@ RUN_TEMACS = ./temacs # Whether builds should contain details. '--no-build-details' or empty. BUILD_DETAILS = @BUILD_DETAILS@ -UNEXEC_OBJ = @UNEXEC_OBJ@ - HAIKU_OBJ = @HAIKU_OBJ@ HAIKU_CXX_OBJ = @HAIKU_CXX_OBJ@ HAIKU_LIBS = @HAIKU_LIBS@ @@ -472,9 +470,9 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \ cmds.o casetab.o casefiddle.o indent.o search.o regex-emacs.o undo.o \ alloc.o pdumper.o data.o doc.o editfns.o callint.o \ eval.o floatfns.o fns.o sort.o font.o print.o lread.o $(MODULES_OBJ) \ - syntax.o $(UNEXEC_OBJ) bytecode.o comp.o $(DYNLIB_OBJ) \ - process.o gnutls.o callproc.o \ - region-cache.o sound.o timefns.o atimer.o \ + syntax.o bytecode.o comp.o $(DYNLIB_OBJ) \ + process.o gnutls.o callproc.o \ + region-cache.o sound.o timefns.o atimer.o \ doprnt.o intervals.o textprop.o composite.o xml.o lcms.o $(NOTIFY_OBJ) \ $(XWIDGETS_OBJ) \ profiler.o decompress.o \ diff --git a/src/alloc.c b/src/alloc.c index b13c3e49224..d3ac975b67b 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -266,7 +266,7 @@ voidfuncptr __MALLOC_HOOK_VOLATILE __malloc_initialize_hook EXTERNALLY_VISIBLE #endif -#if defined DOUG_LEA_MALLOC || defined HAVE_UNEXEC +#if defined DOUG_LEA_MALLOC /* Allocator-related actions to do just before and after unexec. */ @@ -570,15 +570,9 @@ static void mem_delete (struct mem_node *); static void mem_delete_fixup (struct mem_node *); static struct mem_node *mem_find (void *); -/* Addresses of staticpro'd variables. Initialize it to a nonzero - value if we might unexec; otherwise some compilers put it into - BSS. */ +/* Addresses of staticpro'd variables. */ -Lisp_Object const *staticvec[NSTATICS] -#ifdef HAVE_UNEXEC -= {&Vpurify_flag} -#endif - ; +Lisp_Object const *staticvec[NSTATICS]; /* Index of next unused slot in staticvec. */ @@ -631,10 +625,8 @@ mmap_lisp_allowed_p (void) { /* If we can't store all memory addresses in our lisp objects, it's risky to let the heap use mmap and give us addresses from all - over our address space. We also can't use mmap for lisp objects - if we might dump: unexec doesn't preserve the contents of mmapped - regions. */ - return pointers_fit_in_lispobj_p () && !will_dump_with_unexec_p (); + over our address space. */ + return pointers_fit_in_lispobj_p (); } #endif @@ -1074,11 +1066,7 @@ lisp_free (void *block) BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary. */ /* Byte alignment of storage blocks. */ -#ifdef HAVE_UNEXEC -# define BLOCK_ALIGN (1 << 10) -#else /* !HAVE_UNEXEC */ # define BLOCK_ALIGN (1 << 15) -#endif static_assert (POWER_OF_2 (BLOCK_ALIGN)); /* Use aligned_alloc if it or a simple substitute is available. diff --git a/src/buffer.c b/src/buffer.c index a4dc8b12093..07a4e00fa68 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -4892,47 +4892,6 @@ init_buffer (void) { Lisp_Object temp; -#ifdef USE_MMAP_FOR_BUFFERS - if (dumped_with_unexec_p ()) - { - Lisp_Object tail, buffer; - -#ifndef WINDOWSNT - /* These must be reset in the dumped Emacs, to avoid stale - references to mmap'ed memory from before the dump. - - WINDOWSNT doesn't need this because it doesn't track mmap'ed - regions by hand (see w32heap.c, which uses system APIs for - that purpose), and thus doesn't use mmap_regions. */ - mmap_regions = NULL; - mmap_fd = -1; -#endif - - /* The dumped buffers reference addresses of buffer text - recorded by temacs, that cannot be used by the dumped Emacs. - We map new memory for their text here. - - Implementation notes: the buffers we carry from temacs are: - " prin1", "*scratch*", " *Minibuf-0*", "*Messages*", and - " *code-conversion-work*". They are created by - init_buffer_once and init_window_once (which are not called - in the dumped Emacs), and by the first call to coding.c - routines. Since FOR_EACH_LIVE_BUFFER only walks the buffers - in Vbuffer_alist, any buffer we carry from temacs that is - not in the alist (a.k.a. "magic invisible buffers") should - be handled here explicitly. */ - FOR_EACH_LIVE_BUFFER (tail, buffer) - { - struct buffer *b = XBUFFER (buffer); - b->text->beg = NULL; - enlarge_buffer_text (b, 0); - } - /* The " prin1" buffer is not in Vbuffer_alist. */ - XBUFFER (Vprin1_to_string_buffer)->text->beg = NULL; - enlarge_buffer_text (XBUFFER (Vprin1_to_string_buffer), 0); - } -#endif /* USE_MMAP_FOR_BUFFERS */ - AUTO_STRING (scratch, "*scratch*"); Fset_buffer (Fget_buffer_create (scratch, Qnil)); if (NILP (BVAR (&buffer_defaults, enable_multibyte_characters))) diff --git a/src/conf_post.h b/src/conf_post.h index 29d14bf672b..6848d694cd3 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -93,6 +93,31 @@ typedef bool bool_bf; # define ADDRESS_SANITIZER false #endif +/* If HYBRID_MALLOC is defined (e.g., on Cygwin), emacs will use + gmalloc before dumping and the system malloc after dumping. + hybrid_malloc and friends, defined in gmalloc.c, are wrappers that + accomplish this. */ +#ifdef HYBRID_MALLOC +#ifdef emacs +#undef malloc +#define malloc hybrid_malloc +#undef realloc +#define realloc hybrid_realloc +#undef aligned_alloc +#define aligned_alloc hybrid_aligned_alloc +#undef calloc +#define calloc hybrid_calloc +#undef free +#define free hybrid_free + +extern void *hybrid_malloc (size_t); +extern void *hybrid_calloc (size_t, size_t); +extern void hybrid_free (void *); +extern void *hybrid_aligned_alloc (size_t, size_t); +extern void *hybrid_realloc (void *, size_t); +#endif /* emacs */ +#endif /* HYBRID_MALLOC */ + /* We have to go this route, rather than the old hpux9 approach of renaming the functions via macros. The system's stdlib.h has fully prototyped declarations, which yields a conflicting definition of diff --git a/src/emacs.c b/src/emacs.c index 6f005c64351..1b8f400f926 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -196,11 +196,6 @@ bool running_asynch_code; bool display_arg; #endif -#if defined GNU_LINUX && defined HAVE_UNEXEC -/* The gap between BSS end and heap start as far as we can tell. */ -static uintmax_t heap_bss_diff; -#endif - /* To run as a background daemon under Cocoa or Windows, we must do a fork+exec, not a simple fork. @@ -912,14 +907,6 @@ load_pdump (int argc, char **argv, char *dump_file) #endif ; - /* TODO: maybe more thoroughly scrub process environment in order to - make this use case (loading a dump file in an unexeced emacs) - possible? Right now, we assume that things we don't touch are - zero-initialized, and in an unexeced Emacs, this assumption - doesn't hold. */ - if (initialized) - fatal ("cannot load dump file in unexeced Emacs"); - /* Look for an explicitly-specified dump file. */ const char *path_exec = PATH_EXEC; dump_file = NULL; @@ -1318,53 +1305,34 @@ android_emacs_init (int argc, char **argv, char *dump_file) #endif /* Look for this argument first, before any heap allocation, so we - can set heap flags properly if we're going to unexec. */ + can set heap flags properly if we're going to dump. */ if (!initialized && temacs) { -#ifdef HAVE_UNEXEC - if (strcmp (temacs, "dump") == 0 || - strcmp (temacs, "bootstrap") == 0) - gflags.will_dump_with_unexec_ = true; -#endif #ifdef HAVE_PDUMPER if (strcmp (temacs, "pdump") == 0 || strcmp (temacs, "pbootstrap") == 0) gflags.will_dump_with_pdumper_ = true; -#endif -#if defined HAVE_PDUMPER || defined HAVE_UNEXEC if (strcmp (temacs, "bootstrap") == 0 || strcmp (temacs, "pbootstrap") == 0) gflags.will_bootstrap_ = true; gflags.will_dump_ = - will_dump_with_pdumper_p () || - will_dump_with_unexec_p (); + will_dump_with_pdumper_p (); if (will_dump_p ()) dump_mode = temacs; #endif if (!dump_mode) fatal ("Invalid temacs mode '%s'", temacs); } - else if (temacs) - { - fatal ("--temacs not supported for unexeced emacs"); - } else { eassert (!temacs); -#ifndef HAVE_UNEXEC eassert (!initialized); -#endif #ifdef HAVE_PDUMPER if (!initialized) attempt_load_pdump = true; #endif } -#ifdef HAVE_UNEXEC - if (!will_dump_with_unexec_p ()) - gflags.will_not_unexec_ = true; -#endif - #ifdef WINDOWSNT /* Grab our malloc arena space now, before anything important happens. This relies on the static heap being needed only in @@ -1438,25 +1406,12 @@ android_emacs_init (int argc, char **argv, char *dump_file) argc = maybe_disable_address_randomization (argc, argv); -#if defined GNU_LINUX && defined HAVE_UNEXEC - if (!initialized) - { - char *heap_start = my_heap_start (); - heap_bss_diff = heap_start - max (my_endbss, my_endbss_static); - } -#endif #ifdef RUN_TIME_REMAP if (initialized) run_time_remap (argv[0]); #endif -/* If using unexmacosx.c (set by s/darwin.h), we must do this. */ -#if defined DARWIN_OS && defined HAVE_UNEXEC - if (!initialized) - unexec_init_emacs_zone (); -#endif - init_standard_fds (); atexit (close_output_streams); @@ -1638,10 +1593,7 @@ android_emacs_init (int argc, char **argv, char *dump_file) #endif /* MSDOS */ /* Set locale, so that initial error messages are localized properly. - However, skip this if LC_ALL is "C", as it's not needed in that case. - Skipping helps if dumping with unexec, to ensure that the dumped - Emacs does not have its system locale tables initialized, as that - might cause screwups when the dumped Emacs starts up. */ + However, skip this if LC_ALL is "C", as it's not needed in that case. */ char *lc_all = getenv ("LC_ALL"); if (! (lc_all && strcmp (lc_all, "C") == 0)) { @@ -3158,117 +3110,6 @@ shut_down_emacs (int sig, Lisp_Object stuff) } - -#ifdef HAVE_UNEXEC - -#include "unexec.h" - -DEFUN ("dump-emacs", Fdump_emacs, Sdump_emacs, 2, 2, 0, - doc: /* Dump current state of Emacs into executable file FILENAME. -Take symbols from SYMFILE (presumably the file you executed to run Emacs). -This is used in the file `loadup.el' when building Emacs. - -You must run Emacs in batch mode in order to dump it. */) - (Lisp_Object filename, Lisp_Object symfile) -{ - Lisp_Object tem; - Lisp_Object symbol; - specpdl_ref count = SPECPDL_INDEX (); - - check_pure_size (); - - if (! noninteractive) - error ("Dumping Emacs works only in batch mode"); - - if (dumped_with_unexec_p ()) - error ("Emacs can be dumped using unexec only once"); - - if (definitely_will_not_unexec_p ()) - error ("This Emacs instance was not started in temacs mode"); - -# if defined GNU_LINUX && defined HAVE_UNEXEC - - /* Warn if the gap between BSS end and heap start is larger than this. */ -# define MAX_HEAP_BSS_DIFF (1024 * 1024) - - if (heap_bss_diff > MAX_HEAP_BSS_DIFF) - fprintf (stderr, - ("**************************************************\n" - "Warning: Your system has a gap between BSS and the\n" - "heap (%"PRIuMAX" bytes). This usually means that exec-shield\n" - "or something similar is in effect. The dump may\n" - "fail because of this. See the section about\n" - "exec-shield in etc/PROBLEMS for more information.\n" - "**************************************************\n"), - heap_bss_diff); -# endif - - /* Bind `command-line-processed' to nil before dumping, - so that the dumped Emacs will process its command line - and set up to work with X windows if appropriate. */ - symbol = Qcommand_line_processed; - specbind (symbol, Qnil); - - CHECK_STRING (filename); - filename = Fexpand_file_name (filename, Qnil); - filename = ENCODE_FILE (filename); - if (!NILP (symfile)) - { - CHECK_STRING (symfile); - if (SCHARS (symfile)) - { - symfile = Fexpand_file_name (symfile, Qnil); - symfile = ENCODE_FILE (symfile); - } - } - - tem = Vpurify_flag; - Vpurify_flag = Qnil; - -# ifdef HYBRID_MALLOC - { - static char const fmt[] = "%d of %d static heap bytes used"; - char buf[sizeof fmt + 2 * (INT_STRLEN_BOUND (int) - 2)]; - int max_usage = max_bss_sbrk_ptr - bss_sbrk_buffer; - sprintf (buf, fmt, max_usage, STATIC_HEAP_SIZE); - /* Don't log messages, because at this point buffers cannot be created. */ - message1_nolog (buf); - } -# endif - - fflush (stdout); - /* Tell malloc where start of impure now is. */ - /* Also arrange for warnings when nearly out of space. */ -# if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC && !defined WINDOWSNT - /* On Windows, this was done before dumping, and that once suffices. - Meanwhile, my_edata is not valid on Windows. */ - memory_warnings (my_edata, malloc_warning); -# endif - - struct gflags old_gflags = gflags; - gflags.will_dump_ = false; - gflags.will_dump_with_unexec_ = false; - gflags.dumped_with_unexec_ = true; - - alloc_unexec_pre (); - - unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0); - - alloc_unexec_post (); - - gflags = old_gflags; - -# ifdef WINDOWSNT - Vlibrary_cache = Qnil; -# endif - - Vpurify_flag = tem; - - return unbind_to (count, Qnil); -} - -#endif - /* Recover from setlocale (LC_ALL, ""). */ void @@ -3568,10 +3409,6 @@ syms_of_emacs (void) DEFSYM (Qcommand_line_processed, "command-line-processed"); DEFSYM (Qsafe_magic, "safe-magic"); -#ifdef HAVE_UNEXEC - defsubr (&Sdump_emacs); -#endif - defsubr (&Skill_emacs); defsubr (&Sinvocation_name); diff --git a/src/lastfile.c b/src/lastfile.c index a31a30553ca..b8151b440ab 100644 --- a/src/lastfile.c +++ b/src/lastfile.c @@ -42,14 +42,3 @@ along with GNU Emacs. If not, see . */ || defined WINDOWSNT || defined CYGWIN || defined DARWIN_OS) char my_edata[] = "End of Emacs initialized data"; #endif - -#ifdef HAVE_UNEXEC - -/* Help unexec locate the end of the .bss area used by Emacs (which - isn't always a separate section in NT executables). */ -char my_endbss[1]; - -static char _my_endbss[1]; -char * my_endbss_static = _my_endbss; - -#endif diff --git a/src/lisp.h b/src/lisp.h index 2faad895133..3819784fb05 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -639,20 +639,12 @@ extern struct gflags dump. */ bool dumped_with_pdumper_ : 1; #endif -#ifdef HAVE_UNEXEC - bool will_dump_with_unexec_ : 1; - /* Set in an Emacs process that has been restored from an unexec - dump. */ - bool dumped_with_unexec_ : 1; - /* We promise not to unexec: useful for hybrid malloc. */ - bool will_not_unexec_ : 1; -#endif } gflags; INLINE bool will_dump_p (void) { -#if HAVE_PDUMPER || defined HAVE_UNEXEC +#if HAVE_PDUMPER return gflags.will_dump_; #else return false; @@ -662,7 +654,7 @@ will_dump_p (void) INLINE bool will_bootstrap_p (void) { -#if HAVE_PDUMPER || defined HAVE_UNEXEC +#if HAVE_PDUMPER return gflags.will_bootstrap_; #else return false; @@ -689,39 +681,6 @@ dumped_with_pdumper_p (void) #endif } -INLINE bool -will_dump_with_unexec_p (void) -{ -#ifdef HAVE_UNEXEC - return gflags.will_dump_with_unexec_; -#else - return false; -#endif -} - -INLINE bool -dumped_with_unexec_p (void) -{ -#ifdef HAVE_UNEXEC - return gflags.dumped_with_unexec_; -#else - return false; -#endif -} - -/* This function is the opposite of will_dump_with_unexec_p(), except - that it returns false before main runs. It's important to use - gmalloc for any pre-main allocations if we're going to unexec. */ -INLINE bool -definitely_will_not_unexec_p (void) -{ -#ifdef HAVE_UNEXEC - return gflags.will_not_unexec_; -#else - return true; -#endif -} - /* Defined in floatfns.c. */ extern double extract_float (Lisp_Object); @@ -3445,14 +3404,10 @@ CHECK_SUBR (Lisp_Object x) /* If we're not dumping using the legacy dumper and we might be using the portable dumper, try to bunch all the subr structures together for more efficient dump loading. */ -#ifndef HAVE_UNEXEC -# ifdef DARWIN_OS -# define SUBR_SECTION_ATTRIBUTE ATTRIBUTE_SECTION ("__DATA,subrs") -# else -# define SUBR_SECTION_ATTRIBUTE ATTRIBUTE_SECTION (".subrs") -# endif +#ifdef DARWIN_OS +# define SUBR_SECTION_ATTRIBUTE ATTRIBUTE_SECTION ("__DATA,subrs") #else -# define SUBR_SECTION_ATTRIBUTE +# define SUBR_SECTION_ATTRIBUTE ATTRIBUTE_SECTION (".subrs") #endif /* Define a built-in function for calling from Lisp. @@ -4486,8 +4441,6 @@ extern void mark_objects (Lisp_Object *, ptrdiff_t); #if defined REL_ALLOC && !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC extern void refill_memory_reserve (void); #endif -extern void alloc_unexec_pre (void); -extern void alloc_unexec_post (void); extern void mark_c_stack (char const *, char const *); extern void flush_stack_call_func1 (void (*func) (void *arg), void *arg); extern void mark_memory (void const *start, void const *end); @@ -4931,49 +4884,6 @@ void do_debug_on_call (Lisp_Object code, specpdl_ref count); Lisp_Object funcall_general (Lisp_Object fun, ptrdiff_t numargs, Lisp_Object *args); -/* Defined in unexmacosx.c. */ -#if defined DARWIN_OS && defined HAVE_UNEXEC -/* Redirect calls to malloc, realloc and free to a macOS zone memory allocator. - FIXME: Either also redirect unexec_aligned_alloc and unexec_calloc, - or fix this comment to explain why those two redirections are not needed. */ -extern void unexec_init_emacs_zone (void); -extern void *unexec_malloc (size_t); -extern void *unexec_realloc (void *, size_t); -extern void unexec_free (void *); -# ifndef UNEXMACOSX_C -# include -# undef malloc -# undef realloc -# undef free -# define malloc unexec_malloc -# define realloc unexec_realloc -# define free unexec_free -# endif -#endif - -/* Defined in gmalloc.c. */ -#ifdef HYBRID_MALLOC -/* Redirect calls to malloc and friends to a hybrid allocator that - uses gmalloc before dumping and the system malloc after dumping. - This can be useful on Cygwin, for example. */ -extern void *hybrid_aligned_alloc (size_t, size_t); -extern void *hybrid_calloc (size_t, size_t); -extern void *hybrid_malloc (size_t); -extern void *hybrid_realloc (void *, size_t); -extern void hybrid_free (void *); -# include -# undef aligned_alloc -# undef calloc -# undef malloc -# undef realloc -# undef free -# define aligned_alloc hybrid_aligned_alloc -# define calloc hybrid_calloc -# define malloc hybrid_malloc -# define realloc hybrid_realloc -# define free hybrid_free -#endif - /* The definition of Lisp_Module_Function depends on emacs-module.h, so we don't define it here. It's defined in emacs-module.c. */ diff --git a/src/pdumper.c b/src/pdumper.c index bfa790b963a..7b1ec229601 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -4134,12 +4134,6 @@ types. */) "contributing a patch to Emacs."); #endif - if (will_dump_with_unexec_p ()) - error ("This Emacs instance was started under the assumption " - "that it would be dumped with unexec, not the portable " - "dumper. Dumping with the portable dumper may produce " - "unexpected results."); - if (!main_thread_p (current_thread)) error ("This function can be called only in the main thread"); diff --git a/src/process.c b/src/process.c index 275e86f31d0..c7473d3111f 100644 --- a/src/process.c +++ b/src/process.c @@ -8640,50 +8640,39 @@ init_process_emacs (int sockfd) inhibit_sentinels = 0; -#ifdef HAVE_UNEXEC - /* Clear child_signal_read_fd and child_signal_write_fd after dumping, - lest wait_reading_process_output should select on nonexistent file - descriptors which existed in the build process. */ - child_signal_read_fd = -1; - child_signal_write_fd = -1; -#endif /* HAVE_UNEXEC */ +#if defined HAVE_GLIB && !defined WINDOWSNT + /* Tickle Glib's child-handling code. Ask Glib to install a + watch source for Emacs itself which will initialize glib's + private SIGCHLD handler, allowing catch_child_signal to copy + it into lib_child_handler. This is a hacky workaround to get + glib's g_unix_signal_handler into lib_child_handler. + + In Glib 2.37.5 (2013), commit 2e471acf changed Glib to + always install a signal handler when g_child_watch_source_new + is called and not just the first time it's called, and to + reset signal handlers to SIG_DFL when it no longer has a + watcher on that signal. Arrange for Emacs's signal handler + to be reinstalled even if this happens. + + In Glib 2.73.2 (2022), commit f615eef4 changed Glib again, + to not install a signal handler if the system supports + pidfd_open and waitid (as in Linux kernel 5.3+). The hacky + workaround is not needed in this case. */ + GSource *source = g_child_watch_source_new (getpid ()); + catch_child_signal (); + g_source_unref (source); - if (!will_dump_with_unexec_p ()) + if (lib_child_handler != dummy_handler) { -#if defined HAVE_GLIB && !defined WINDOWSNT - /* Tickle Glib's child-handling code. Ask Glib to install a - watch source for Emacs itself which will initialize glib's - private SIGCHLD handler, allowing catch_child_signal to copy - it into lib_child_handler. This is a hacky workaround to get - glib's g_unix_signal_handler into lib_child_handler. - - In Glib 2.37.5 (2013), commit 2e471acf changed Glib to - always install a signal handler when g_child_watch_source_new - is called and not just the first time it's called, and to - reset signal handlers to SIG_DFL when it no longer has a - watcher on that signal. Arrange for Emacs's signal handler - to be reinstalled even if this happens. - - In Glib 2.73.2 (2022), commit f615eef4 changed Glib again, - to not install a signal handler if the system supports - pidfd_open and waitid (as in Linux kernel 5.3+). The hacky - workaround is not needed in this case. */ - GSource *source = g_child_watch_source_new (getpid ()); + /* The hacky workaround is needed on this platform. */ + signal_handler_t lib_child_handler_glib = lib_child_handler; catch_child_signal (); - g_source_unref (source); - - if (lib_child_handler != dummy_handler) - { - /* The hacky workaround is needed on this platform. */ - signal_handler_t lib_child_handler_glib = lib_child_handler; - catch_child_signal (); - eassert (lib_child_handler == dummy_handler); - lib_child_handler = lib_child_handler_glib; - } + eassert (lib_child_handler == dummy_handler); + lib_child_handler = lib_child_handler_glib; + } #else - catch_child_signal (); + catch_child_signal (); #endif - } #ifdef HAVE_SETRLIMIT /* Don't allocate more than FD_SETSIZE file descriptors for Emacs itself. */ diff --git a/src/sysdep.c b/src/sysdep.c index 3d9c49d9280..5bf2780920b 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -165,9 +165,7 @@ maybe_disable_address_randomization (int argc, char **argv) if (argc < 2 || strcmp (argv[1], aslr_disabled_option) != 0) { - /* If dumping via unexec, ASLR must be disabled, as otherwise - data may be scattered and undumpable as a simple executable. - If pdumping, disabling ASLR lessens differences in the .pdmp file. */ + /* If pdumping, disabling ASLR lessens differences in the .pdmp file. */ bool disable_aslr = will_dump_p (); # ifdef __PPC64__ disable_aslr = true; @@ -2036,12 +2034,6 @@ init_signals (void) main_thread_id = pthread_self (); #endif - /* Don't alter signal handlers if dumping with unexec. On some - machines, changing signal handlers sets static data that would make - signals fail to work right when the dumped Emacs is run. */ - if (will_dump_with_unexec_p ()) - return; - sigfillset (&process_fatal_action.sa_mask); process_fatal_action.sa_handler = deliver_fatal_signal; process_fatal_action.sa_flags = emacs_sigaction_flags (); diff --git a/src/timefns.c b/src/timefns.c index 590d84c4d65..aab4dbb9206 100644 --- a/src/timefns.c +++ b/src/timefns.c @@ -318,37 +318,8 @@ tzlookup (Lisp_Object zone, bool settz) void init_timefns (void) { -#ifdef HAVE_UNEXEC - /* A valid but unlikely setting for the TZ environment variable. - It is OK (though a bit slower) if the user chooses this value. */ - static char dump_tz_string[] = "TZ=UtC0"; - - /* When just dumping out, set the time zone to a known unlikely value - and skip the rest of this function. */ - if (will_dump_with_unexec_p ()) - { - xputenv (dump_tz_string); - tzset (); - return; - } -#endif - char *tz = getenv ("TZ"); -#ifdef HAVE_UNEXEC - /* If the execution TZ happens to be the same as the dump TZ, - change it to some other value and then change it back, - to force the underlying implementation to reload the TZ info. - This is needed on implementations that load TZ info from files, - since the TZ file contents may differ between dump and execution. */ - if (tz && strcmp (tz, &dump_tz_string[tzeqlen]) == 0) - { - ++*tz; - tzset (); - --*tz; - } -#endif - /* Set the time zone rule now, so that the call to putenv is done before multiple threads are active. */ tzlookup (tz ? build_string (tz) : Qwall, true); diff --git a/src/w32heap.c b/src/w32heap.c index 546a37ffd80..abf43d33a98 100644 --- a/src/w32heap.c +++ b/src/w32heap.c @@ -617,31 +617,6 @@ sys_calloc (size_t number, size_t size) return ptr; } -#if defined HAVE_UNEXEC && defined ENABLE_CHECKING -void -report_temacs_memory_usage (void) -{ - DWORD blocks_used = 0; - size_t large_mem_used = 0; - int i; - - for (i = 0; i < blocks_number; i++) - if (blocks[i].occupied) - { - blocks_used++; - large_mem_used += blocks[i].size; - } - - /* Emulate 'message', which writes to stderr in non-interactive - sessions. */ - fprintf (stderr, - "Dump memory usage: Heap: %" PRIu64 " Large blocks(%lu/%lu): %" PRIu64 "/%" PRIu64 "\n", - (unsigned long long)committed, blocks_used, blocks_number, - (unsigned long long)large_mem_used, - (unsigned long long)(dumped_data + DUMPED_HEAP_SIZE - bc_limit)); -} -#endif - /* Emulate getpagesize. */ int getpagesize (void) diff --git a/src/w32heap.h b/src/w32heap.h index 73fc601af34..901c9b5a41e 100644 --- a/src/w32heap.h +++ b/src/w32heap.h @@ -1,5 +1,5 @@ -/* Heap management routines (including unexec) for GNU Emacs on Windows NT. - Copyright (C) 1994, 2001-2025 Free Software Foundation, Inc. +/* Heap management routines for GNU Emacs on Windows NT. + Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/w32image.c b/src/w32image.c index ed3803051b4..30930e94d90 100644 --- a/src/w32image.c +++ b/src/w32image.c @@ -634,6 +634,4 @@ syms_of_w32image (void) void globals_of_w32image (void) { - /* This is only needed in an unexec build. */ - memset (&last_encoder, 0, sizeof last_encoder); } -- 2.39.5