summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in60
-rw-r--r--src/alloc.c734
-rw-r--r--src/androidterm.c2
-rw-r--r--src/buffer.c57
-rw-r--r--src/bytecode.c3
-rw-r--r--src/callint.c8
-rw-r--r--src/callproc.c28
-rw-r--r--src/category.c4
-rw-r--r--src/coding.c18
-rw-r--r--src/comp.c189
-rw-r--r--src/comp.h10
-rw-r--r--src/conf_post.h35
-rw-r--r--src/data.c38
-rw-r--r--src/dbusbind.c4
-rw-r--r--src/deps.mk21
-rw-r--r--src/doc.c1
-rw-r--r--src/emacs-module.c28
-rw-r--r--src/emacs.c205
-rw-r--r--src/eval.c19
-rw-r--r--src/fileio.c28
-rw-r--r--src/firstfile.c32
-rw-r--r--src/fns.c37
-rw-r--r--src/fontset.c4
-rw-r--r--src/frame.c4
-rw-r--r--src/gmalloc.c167
-rw-r--r--src/haikufns.c2
-rw-r--r--src/image.c2
-rw-r--r--src/intervals.c2
-rw-r--r--src/json.c2
-rw-r--r--src/keyboard.c6
-rw-r--r--src/keymap.c35
-rw-r--r--src/lastfile.c55
-rw-r--r--src/lisp.h135
-rw-r--r--src/lread.c46
-rw-r--r--src/pdumper.c18
-rw-r--r--src/pgtkfns.c4
-rw-r--r--src/pgtkterm.c4
-rw-r--r--src/print.c3
-rw-r--r--src/process.c71
-rw-r--r--src/profiler.c2
-rw-r--r--src/puresize.h115
-rw-r--r--src/ralloc.c6
-rw-r--r--src/search.c12
-rw-r--r--src/sheap.c79
-rw-r--r--src/sheap.h30
-rw-r--r--src/sqlite.c8
-rw-r--r--src/syntax.c4
-rw-r--r--src/sysdep.c14
-rw-r--r--src/timefns.c29
-rw-r--r--src/treesit.c36
-rw-r--r--src/unexaix.c611
-rw-r--r--src/unexcoff.c540
-rw-r--r--src/unexcw.c302
-rw-r--r--src/unexec.h4
-rw-r--r--src/unexelf.c658
-rw-r--r--src/unexhp9k800.c324
-rw-r--r--src/unexmacosx.c1401
-rw-r--r--src/unexsol.c28
-rw-r--r--src/unexw32.c684
-rw-r--r--src/w32fns.c4
-rw-r--r--src/w32heap.c345
-rw-r--r--src/w32heap.h4
-rw-r--r--src/w32image.c2
-rw-r--r--src/xdisp.c18
-rw-r--r--src/xfaces.c4
-rw-r--r--src/xfns.c9
-rw-r--r--src/xftfont.c2
-rw-r--r--src/xterm.c4
68 files changed, 430 insertions, 6970 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index d987124d29d..8296329f136 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -127,16 +127,6 @@ LD_SWITCH_SYSTEM_TEMACS=@LD_SWITCH_SYSTEM_TEMACS@
## Flags to pass to ld only for temacs.
TEMACS_LDFLAGS = $(LD_SWITCH_SYSTEM) $(LD_SWITCH_SYSTEM_TEMACS)
-## If needed, the names of the paxctl and setfattr programs.
-## On grsecurity/PaX systems, unexec will fail due to a gap between
-## the bss section and the heap. Older versions need paxctl to work
-## around this, newer ones setfattr. See Bug#11398 and Bug#16343.
-PAXCTL = @PAXCTL@
-SETFATTR = @SETFATTR@
-## Commands to set PaX flags on dumped and not-dumped instances of Emacs.
-PAXCTL_dumped = @PAXCTL_dumped@
-PAXCTL_notdumped = @PAXCTL_notdumped@
-
## Some systems define this to request special libraries.
LIBS_SYSTEM=@LIBS_SYSTEM@
@@ -307,8 +297,6 @@ XSHAPE_CFLAGS = @XSHAPE_CFLAGS@
## widget.o if USE_X_TOOLKIT, otherwise empty.
WIDGET_OBJ=@WIDGET_OBJ@
-HYBRID_MALLOC = @HYBRID_MALLOC@
-
## cygw32.o if CYGWIN, otherwise empty.
CYGWIN_OBJ=@CYGWIN_OBJ@
@@ -387,8 +375,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@
@@ -461,8 +447,6 @@ ALL_CXX_CFLAGS = $(EMACS_CFLAGS) \
.cc.o:
$(AM_V_CXX)$(CXX) -c $(CPPFLAGS) $(ALL_CXX_CFLAGS) $(PROFILING_CFLAGS) $<
-## lastfile must follow all files whose initialized data areas should
-## be dumped as pure by dump-emacs.
base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
charset.o coding.o category.o ccl.o character.o chartab.o bidi.o \
$(CM_OBJ) term.o terminal.o xfaces.o $(XOBJ) $(GTK_OBJ) $(DBUS_OBJ) \
@@ -472,15 +456,14 @@ 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 \
thread.o systhread.o sqlite.o treesit.o \
itree.o json.o \
- $(if $(HYBRID_MALLOC),sheap.o) \
$(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
$(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) \
$(HAIKU_OBJ) $(PGTK_OBJ) $(ANDROID_OBJ)
@@ -512,19 +495,11 @@ VMLIMIT_OBJ=@VMLIMIT_OBJ@
## ralloc.o if !SYSTEM_MALLOC && REL_ALLOC, else empty.
RALLOC_OBJ=@RALLOC_OBJ@
-## Empty on Cygwin and MinGW, lastfile.o elsewhere.
-PRE_ALLOC_OBJ=@PRE_ALLOC_OBJ@
-## lastfile.o on Cygwin and MinGW, empty elsewhere.
-POST_ALLOC_OBJ=@POST_ALLOC_OBJ@
-
## List of object files that make-docfile should not be told about.
-otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \
- $(POST_ALLOC_OBJ) $(WIDGET_OBJ) $(LIBOBJS)
+otherobj= $(TERMCAP_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) $(WIDGET_OBJ) $(LIBOBJS)
## All object files linked into temacs. $(VMLIMIT_OBJ) should be first.
-## (On MinGW, firstfile.o should be before vm-limit.o.)
-FIRSTFILE_OBJ=@FIRSTFILE_OBJ@
-ALLOBJS = $(FIRSTFILE_OBJ) $(VMLIMIT_OBJ) $(obj) $(otherobj)
+ALLOBJS = $(VMLIMIT_OBJ) $(obj) $(otherobj)
# Must be first, before dep inclusion!
ifneq ($(HAVE_BE_APP),yes)
@@ -658,15 +633,7 @@ emacs$(EXEEXT): temacs$(EXEEXT) \
ifeq ($(SYSTEM_TYPE),cygwin)
find ${top_builddir} -name '*.eln' | rebase -v -O -T -
endif
-ifeq ($(DUMPING),unexec)
- LC_ALL=C $(RUN_TEMACS) -batch $(BUILD_DETAILS) -l loadup --temacs=dump
- ifneq ($(PAXCTL_dumped),)
- $(PAXCTL_dumped) emacs$(EXEEXT)
- endif
- cp -f $@ bootstrap-emacs$(EXEEXT)
-else
rm -f $@ && cp -f temacs$(EXEEXT) $@
-endif
## On Haiku, also produce a binary named Emacs with the appropriate
## icon set.
@@ -721,7 +688,7 @@ globals.h: gl-stamp; @true
$(ALLOBJS): globals.h
-LIBEGNU_ARCHIVE = $(lib)/lib$(if $(HYBRID_MALLOC),e)gnu.a
+LIBEGNU_ARCHIVE = $(lib)/libgnu.a
$(LIBEGNU_ARCHIVE): $(config_h)
$(MAKE) -C $(dir $@) all
@@ -755,11 +722,6 @@ endif
endif
$(AM_V_at)mv $@.tmp $@
$(MKDIR_P) $(etc)
-ifeq ($(DUMPING),unexec)
- ifneq ($(PAXCTL_notdumped),)
- $(PAXCTL_notdumped) $@
- endif
-endif
ifeq ($(XCONFIGURE),android)
## The Android package internally links to a shared library named
@@ -995,21 +957,11 @@ endif
bootstrap-emacs$(EXEEXT): temacs$(EXEEXT)
$(MAKE) -C ../lisp update-subdirs
-ifeq ($(DUMPING),unexec)
- $(RUN_TEMACS) --batch $(BUILD_DETAILS) -l loadup --temacs=bootstrap
- ifneq ($(PAXCTL_dumped),)
- $(PAXCTL_dumped) emacs$(EXEEXT)
- endif
- mv -f emacs$(EXEEXT) bootstrap-emacs$(EXEEXT)
- @: Compile some files earlier to speed up further compilation.
- $(MAKE) -C ../lisp compile-first EMACS="$(bootstrap_exe)"
-else
@: In the pdumper case, make compile-first after the dump
cp -f temacs$(EXEEXT) bootstrap-emacs$(EXEEXT)
ifeq ($(DO_CODESIGN),yes)
codesign -s - -f bootstrap-emacs$(EXEEXT)
endif
-endif
ifeq ($(DUMPING),pdumper)
$(bootstrap_pdmp): bootstrap-emacs$(EXEEXT)
diff --git a/src/alloc.c b/src/alloc.c
index b13c3e49224..40a59854a87 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -33,7 +33,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "bignum.h"
#include "dispextern.h"
#include "intervals.h"
-#include "puresize.h"
#include "sysstdio.h"
#include "systime.h"
#include "character.h"
@@ -127,7 +126,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
marked objects. */
#if (defined SYSTEM_MALLOC || defined DOUG_LEA_MALLOC \
- || defined HYBRID_MALLOC || GC_CHECK_MARKED_OBJECTS)
+ || GC_CHECK_MARKED_OBJECTS)
#undef GC_MALLOC_CHECK
#endif
@@ -210,10 +209,6 @@ enum { MALLOC_ALIGNMENT = max (2 * sizeof (size_t), alignof (long double)) };
# define MMAP_MAX_AREAS 100000000
-/* A pointer to the memory allocated that copies that static data
- inside glibc's malloc. */
-static void *malloc_state_ptr;
-
/* Restore the dumped malloc state. Because malloc can be invoked
even before main (e.g. by the dynamic linker), the dumped malloc
state must be restored as early as possible using this special hook. */
@@ -224,9 +219,6 @@ malloc_initialize_hook (void)
if (! initialized)
{
-# ifdef GNU_LINUX
- my_heap_start ();
-# endif
malloc_using_checking = getenv ("MALLOC_CHECK_") != NULL;
}
else
@@ -248,10 +240,6 @@ malloc_initialize_hook (void)
break;
}
}
-
- if (malloc_set_state (malloc_state_ptr) != 0)
- emacs_abort ();
- alloc_unexec_post ();
}
}
@@ -266,43 +254,6 @@ voidfuncptr __MALLOC_HOOK_VOLATILE __malloc_initialize_hook EXTERNALLY_VISIBLE
#endif
-#if defined DOUG_LEA_MALLOC || defined HAVE_UNEXEC
-
-/* Allocator-related actions to do just before and after unexec. */
-
-void
-alloc_unexec_pre (void)
-{
-# ifdef DOUG_LEA_MALLOC
- malloc_state_ptr = malloc_get_state ();
- if (!malloc_state_ptr)
- fatal ("malloc_get_state: %s", strerror (errno));
-# endif
-}
-
-void
-alloc_unexec_post (void)
-{
-# ifdef DOUG_LEA_MALLOC
- free (malloc_state_ptr);
-# endif
-}
-
-# ifdef GNU_LINUX
-
-/* The address where the heap starts. */
-void *
-my_heap_start (void)
-{
- static void *start;
- if (! start)
- start = sbrk (0);
- return start;
-}
-# endif
-
-#endif
-
/* Mark, unmark, query mark bit of a Lisp string. S must be a pointer
to a struct Lisp_String. */
@@ -380,33 +331,6 @@ static char *spare_memory[7];
#define SPARE_MEMORY (1 << 14)
-/* Initialize it to a nonzero value to force it into data space
- (rather than bss space). That way unexec will remap it into text
- space (pure), on some systems. We have not implemented the
- remapping on more recent systems because this is less important
- nowadays than in the days of small memories and timesharing. */
-
-EMACS_INT pure[(PURESIZE + sizeof (EMACS_INT) - 1) / sizeof (EMACS_INT)] = {1,};
-#define PUREBEG (char *) pure
-
-/* Pointer to the pure area, and its size. */
-
-static char *purebeg;
-static ptrdiff_t pure_size;
-
-/* Number of bytes of pure storage used before pure storage overflowed.
- If this is non-zero, this implies that an overflow occurred. */
-
-static ptrdiff_t pure_bytes_used_before_overflow;
-
-/* Index in pure at which next pure Lisp object will be allocated.. */
-
-static ptrdiff_t pure_bytes_used_lisp;
-
-/* Number of bytes allocated for non-Lisp objects in pure storage. */
-
-static ptrdiff_t pure_bytes_used_non_lisp;
-
/* If positive, garbage collection is inhibited. Otherwise, zero. */
intptr_t garbage_collection_inhibited;
@@ -457,10 +381,9 @@ static struct Lisp_Vector *allocate_clear_vector (ptrdiff_t, bool);
static void unchain_finalizer (struct Lisp_Finalizer *);
static void mark_terminals (void);
static void gc_sweep (void);
-static Lisp_Object make_pure_vector (ptrdiff_t);
static void mark_buffer (struct buffer *);
-#if !defined REL_ALLOC || defined SYSTEM_MALLOC || defined HYBRID_MALLOC
+#if !defined REL_ALLOC || defined SYSTEM_MALLOC
static void refill_memory_reserve (void);
#endif
static void compact_small_strings (void);
@@ -570,29 +493,21 @@ 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. */
int staticidx;
-static void *pure_alloc (size_t, int);
-
-/* Return PTR rounded up to the next multiple of ALIGNMENT. */
-
+#ifndef HAVE_ALIGNED_ALLOC
static void *
pointer_align (void *ptr, int alignment)
{
return (void *) ROUNDUP ((uintptr_t) ptr, alignment);
}
+#endif
/* Extract the pointer hidden within O. */
@@ -631,10 +546,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
@@ -652,7 +565,7 @@ struct Lisp_Finalizer doomed_finalizers;
Malloc
************************************************************************/
-#if defined SIGDANGER || (!defined SYSTEM_MALLOC && !defined HYBRID_MALLOC)
+#if defined SIGDANGER || (!defined SYSTEM_MALLOC)
/* Function malloc calls this if it finds we are near exhausting storage. */
@@ -1074,26 +987,17 @@ 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.
- Aligned allocation is incompatible with unexmacosx.c, so don't use
- it on Darwin if HAVE_UNEXEC. */
-
-#if ! (defined DARWIN_OS && defined HAVE_UNEXEC)
-# if (defined HAVE_ALIGNED_ALLOC \
- || (defined HYBRID_MALLOC \
- ? defined HAVE_POSIX_MEMALIGN \
- : !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC))
-# define USE_ALIGNED_ALLOC 1
-# elif !defined HYBRID_MALLOC && defined HAVE_POSIX_MEMALIGN
-# define USE_ALIGNED_ALLOC 1
-# define aligned_alloc my_aligned_alloc /* Avoid collision with lisp.h. */
+/* Use aligned_alloc if it or a simple substitute is available. */
+
+#if (defined HAVE_ALIGNED_ALLOC \
+ || (!defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC))
+# define USE_ALIGNED_ALLOC 1
+#elif defined HAVE_POSIX_MEMALIGN
+# define USE_ALIGNED_ALLOC 1
+# define aligned_alloc my_aligned_alloc /* Avoid collision with lisp.h. */
static void *
aligned_alloc (size_t alignment, size_t size)
{
@@ -1106,7 +1010,6 @@ aligned_alloc (size_t alignment, size_t size)
void *p;
return posix_memalign (&p, alignment, size) == 0 ? p : 0;
}
-# endif
#endif
/* Padding to leave at the end of a malloc'd block. This is to give
@@ -1662,12 +1565,30 @@ static ptrdiff_t const STRING_BYTES_MAX =
/* Initialize string allocation. Called from init_alloc_once. */
+static struct Lisp_String *allocate_string (void);
+static void
+allocate_string_data (struct Lisp_String *s,
+ EMACS_INT nchars, EMACS_INT nbytes, bool clearit,
+ bool immovable);
+
static void
init_strings (void)
{
- empty_unibyte_string = make_pure_string ("", 0, 0, 0);
+ /* String allocation code will return one of 'empty_*ibyte_string'
+ when asked to construct a new 0-length string, so in order to build
+ those special cases, we have to do it "by hand". */
+ struct Lisp_String *ems = allocate_string ();
+ struct Lisp_String *eus = allocate_string ();
+ ems->u.s.intervals = NULL;
+ eus->u.s.intervals = NULL;
+ allocate_string_data (ems, 0, 0, false, false);
+ allocate_string_data (eus, 0, 0, false, false);
+ /* We can't use 'STRING_SET_UNIBYTE' because this one includes a hack
+ * to redirect its arg to 'empty_unibyte_string' when nbytes == 0. */
+ eus->u.s.size_byte = -1;
+ XSETSTRING (empty_multibyte_string, ems);
+ XSETSTRING (empty_unibyte_string, eus);
staticpro (&empty_unibyte_string);
- empty_multibyte_string = make_pure_string ("", 0, 0, 1);
staticpro (&empty_multibyte_string);
}
@@ -1720,7 +1641,7 @@ string_bytes (struct Lisp_String *s)
ptrdiff_t nbytes =
(s->u.s.size_byte < 0 ? s->u.s.size & ~ARRAY_MARK_FLAG : s->u.s.size_byte);
- if (!PURE_P (s) && !pdumper_object_p (s) && s->u.s.data
+ if (!pdumper_object_p (s) && s->u.s.data
&& nbytes != SDATA_NBYTES (SDATA_OF_STRING (s)))
emacs_abort ();
return nbytes;
@@ -2571,7 +2492,7 @@ pin_string (Lisp_Object string)
unsigned char *data = s->u.s.data;
if (!(size > LARGE_STRING_BYTES
- || PURE_P (data) || pdumper_object_p (data)
+ || pdumper_object_p (data)
|| s->u.s.size_byte == -3))
{
eassert (s->u.s.size_byte == -1);
@@ -2870,17 +2791,16 @@ list5 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4,
}
/* Make a list of COUNT Lisp_Objects, where ARG is the first one.
- Use CONS to construct the pairs. AP has any remaining args. */
+ AP has any remaining args. */
static Lisp_Object
-cons_listn (ptrdiff_t count, Lisp_Object arg,
- Lisp_Object (*cons) (Lisp_Object, Lisp_Object), va_list ap)
+cons_listn (ptrdiff_t count, Lisp_Object arg, va_list ap)
{
eassume (0 < count);
- Lisp_Object val = cons (arg, Qnil);
+ Lisp_Object val = Fcons (arg, Qnil);
Lisp_Object tail = val;
for (ptrdiff_t i = 1; i < count; i++)
{
- Lisp_Object elem = cons (va_arg (ap, Lisp_Object), Qnil);
+ Lisp_Object elem = Fcons (va_arg (ap, Lisp_Object), Qnil);
XSETCDR (tail, elem);
tail = elem;
}
@@ -2893,18 +2813,7 @@ listn (ptrdiff_t count, Lisp_Object arg1, ...)
{
va_list ap;
va_start (ap, arg1);
- Lisp_Object val = cons_listn (count, arg1, Fcons, ap);
- va_end (ap);
- return val;
-}
-
-/* Make a pure list of COUNT Lisp_Objects, where ARG1 is the first one. */
-Lisp_Object
-pure_listn (ptrdiff_t count, Lisp_Object arg1, ...)
-{
- va_list ap;
- va_start (ap, arg1);
- Lisp_Object val = cons_listn (count, arg1, pure_cons, ap);
+ Lisp_Object val = cons_listn (count, arg1, ap);
va_end (ap);
return val;
}
@@ -3085,7 +2994,7 @@ static ptrdiff_t last_inserted_vector_free_idx = VECTOR_FREE_LIST_ARRAY_SIZE;
static struct large_vector *large_vectors;
-/* The only vector with 0 slots, allocated from pure space. */
+/* The only vector with 0 slots. */
Lisp_Object zero_vector;
@@ -3137,14 +3046,8 @@ allocate_vector_block (void)
return block;
}
-/* Called once to initialize vector allocation. */
-
-static void
-init_vectors (void)
-{
- zero_vector = make_pure_vector (0);
- staticpro (&zero_vector);
-}
+static struct Lisp_Vector *
+allocate_vector_from_block (ptrdiff_t nbytes);
/* Memory footprint in bytes of a pseudovector other than a bool-vector. */
static ptrdiff_t
@@ -3157,6 +3060,31 @@ pseudovector_nbytes (const union vectorlike_header *hdr)
return vroundup (header_size + word_size * nwords);
}
+/* Called once to initialize vector allocation. */
+
+static void
+init_vectors (void)
+{
+ /* The normal vector allocation code refuses to allocate a 0-length vector
+ because we use the first field of vectors internally when they're on
+ the free list, so we can't put a zero-length vector on the free list.
+ This is not a problem for 'zero_vector' since it's always reachable.
+ An alternative approach would be to allocate zero_vector outside of the
+ normal heap, e.g. as a static object, and then to "hide" it from the GC,
+ for example by marking it by hand at the beginning of the GC and unmarking
+ it by hand at the end. */
+ struct vector_block *block = allocate_vector_block ();
+ struct Lisp_Vector *zv = (struct Lisp_Vector *)block->data;
+ zv->header.size = 0;
+ ssize_t nbytes = pseudovector_nbytes (&zv->header);
+ ssize_t restbytes = VECTOR_BLOCK_BYTES - nbytes;
+ eassert (restbytes % roundup_size == 0);
+ setup_on_free_list (ADVANCE (zv, nbytes), restbytes);
+
+ zero_vector = make_lisp_ptr (zv, Lisp_Vectorlike);
+ staticpro (&zero_vector);
+}
+
/* Allocate vector from a vector block. */
static struct Lisp_Vector *
@@ -3764,13 +3692,6 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT
/* Bytecode must be immovable. */
pin_string (args[CLOSURE_CODE]);
- /* We used to purecopy everything here, if purify-flag was set. This worked
- OK for Emacs-23, but with Emacs-24's lexical binding code, it can be
- dangerous, since make-byte-code is used during execution to build
- closures, so any closure built during the preload phase would end up
- copied into pure space, including its free variables, which is sometimes
- just wasteful and other times plainly wrong (e.g. those free vars may want
- to be setcar'd). */
Lisp_Object val = Fvector (nargs, args);
XSETPVECTYPE (XVECTOR (val), PVEC_CLOSURE);
return val;
@@ -3850,13 +3771,6 @@ struct symbol_block
static struct symbol_block *symbol_block;
static int symbol_block_index = SYMBOL_BLOCK_SIZE;
-/* Pointer to the first symbol_block that contains pinned symbols.
- Tests for 24.4 showed that at dump-time, Emacs contains about 15K symbols,
- 10K of which are pinned (and all but 250 of them are interned in obarray),
- whereas a "typical session" has in the order of 30K symbols.
- `symbol_block_pinned' lets mark_pinned_symbols scan only 15K symbols rather
- than 30K to find the 10K symbols we need to mark. */
-static struct symbol_block *symbol_block_pinned;
/* List of free symbols. */
@@ -3882,7 +3796,6 @@ init_symbol (Lisp_Object val, Lisp_Object name)
p->u.s.interned = SYMBOL_UNINTERNED;
p->u.s.trapped_write = SYMBOL_UNTRAPPED_WRITE;
p->u.s.declared_special = false;
- p->u.s.pinned = false;
}
DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0,
@@ -4373,7 +4286,7 @@ memory_full (size_t nbytes)
void
refill_memory_reserve (void)
{
-#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
+#if !defined SYSTEM_MALLOC
if (spare_memory[0] == 0)
spare_memory[0] = malloc (SPARE_MEMORY);
if (spare_memory[1] == 0)
@@ -5522,8 +5435,6 @@ valid_lisp_object_p (Lisp_Object obj)
return 1;
void *p = XPNTR (obj);
- if (PURE_P (p))
- return 1;
if (BARE_SYMBOL_P (obj) && c_symbol_p (p))
return ((char *) p - (char *) lispsym) % sizeof lispsym[0] == 0;
@@ -5602,433 +5513,6 @@ hash_table_free_bytes (void *p, ptrdiff_t nbytes)
xfree (p);
}
-
-/***********************************************************************
- Pure Storage Management
- ***********************************************************************/
-
-/* Allocate room for SIZE bytes from pure Lisp storage and return a
- pointer to it. TYPE is the Lisp type for which the memory is
- allocated. TYPE < 0 means it's not used for a Lisp object,
- and that the result should have an alignment of -TYPE.
-
- The bytes are initially zero.
-
- If pure space is exhausted, allocate space from the heap. This is
- merely an expedient to let Emacs warn that pure space was exhausted
- and that Emacs should be rebuilt with a larger pure space. */
-
-static void *
-pure_alloc (size_t size, int type)
-{
- void *result;
- static bool pure_overflow_warned = false;
-
- again:
- if (type >= 0)
- {
- /* Allocate space for a Lisp object from the beginning of the free
- space with taking account of alignment. */
- result = pointer_align (purebeg + pure_bytes_used_lisp, LISP_ALIGNMENT);
- pure_bytes_used_lisp = ((char *)result - (char *)purebeg) + size;
- }
- else
- {
- /* Allocate space for a non-Lisp object from the end of the free
- space. */
- ptrdiff_t unaligned_non_lisp = pure_bytes_used_non_lisp + size;
- char *unaligned = purebeg + pure_size - unaligned_non_lisp;
- int decr = (intptr_t) unaligned & (-1 - type);
- pure_bytes_used_non_lisp = unaligned_non_lisp + decr;
- result = unaligned - decr;
- }
- pure_bytes_used = pure_bytes_used_lisp + pure_bytes_used_non_lisp;
-
- if (pure_bytes_used <= pure_size)
- return result;
-
- if (!pure_overflow_warned)
- {
- message ("Pure Lisp storage overflowed");
- pure_overflow_warned = true;
- }
-
- /* Don't allocate a large amount here,
- because it might get mmap'd and then its address
- might not be usable. */
- int small_amount = 10000;
- eassert (size <= small_amount - LISP_ALIGNMENT);
- purebeg = xzalloc (small_amount);
- pure_size = small_amount;
- pure_bytes_used_before_overflow += pure_bytes_used - size;
- pure_bytes_used = 0;
- pure_bytes_used_lisp = pure_bytes_used_non_lisp = 0;
-
- /* Can't GC if pure storage overflowed because we can't determine
- if something is a pure object or not. */
- garbage_collection_inhibited++;
- goto again;
-}
-
-/* Print a warning if PURESIZE is too small. */
-
-void
-check_pure_size (void)
-{
- if (pure_bytes_used_before_overflow)
- message (("emacs:0:Pure Lisp storage overflow (approx. %jd"
- " bytes needed)"),
- pure_bytes_used + pure_bytes_used_before_overflow);
-}
-
-/* Find the byte sequence {DATA[0], ..., DATA[NBYTES-1], '\0'} from
- the non-Lisp data pool of the pure storage, and return its start
- address. Return NULL if not found. */
-
-static char *
-find_string_data_in_pure (const char *data, ptrdiff_t nbytes)
-{
- int i;
- ptrdiff_t skip, bm_skip[256], last_char_skip, infinity, start, start_max;
- const unsigned char *p;
- char *non_lisp_beg;
-
- if (pure_bytes_used_non_lisp <= nbytes)
- return NULL;
-
- /* The Android GCC generates code like:
-
- 0xa539e755 <+52>: lea 0x430(%esp),%esi
-=> 0xa539e75c <+59>: movdqa %xmm0,0x0(%ebp)
- 0xa539e761 <+64>: add $0x10,%ebp
-
- but data is not aligned appropriately, so a GP fault results. */
-
-#if defined __i386__ \
- && defined HAVE_ANDROID \
- && !defined ANDROID_STUBIFY \
- && !defined (__clang__)
- if ((intptr_t) data & 15)
- return NULL;
-#endif
-
- /* Set up the Boyer-Moore table. */
- skip = nbytes + 1;
- for (i = 0; i < 256; i++)
- bm_skip[i] = skip;
-
- p = (const unsigned char *) data;
- while (--skip > 0)
- bm_skip[*p++] = skip;
-
- last_char_skip = bm_skip['\0'];
-
- non_lisp_beg = purebeg + pure_size - pure_bytes_used_non_lisp;
- start_max = pure_bytes_used_non_lisp - (nbytes + 1);
-
- /* See the comments in the function `boyer_moore' (search.c) for the
- use of `infinity'. */
- infinity = pure_bytes_used_non_lisp + 1;
- bm_skip['\0'] = infinity;
-
- p = (const unsigned char *) non_lisp_beg + nbytes;
- start = 0;
- do
- {
- /* Check the last character (== '\0'). */
- do
- {
- start += bm_skip[*(p + start)];
- }
- while (start <= start_max);
-
- if (start < infinity)
- /* Couldn't find the last character. */
- return NULL;
-
- /* No less than `infinity' means we could find the last
- character at `p[start - infinity]'. */
- start -= infinity;
-
- /* Check the remaining characters. */
- if (memcmp (data, non_lisp_beg + start, nbytes) == 0)
- /* Found. */
- return non_lisp_beg + start;
-
- start += last_char_skip;
- }
- while (start <= start_max);
-
- return NULL;
-}
-
-
-/* Return a string allocated in pure space. DATA is a buffer holding
- NCHARS characters, and NBYTES bytes of string data. MULTIBYTE
- means make the result string multibyte.
-
- Must get an error if pure storage is full, since if it cannot hold
- a large string it may be able to hold conses that point to that
- string; then the string is not protected from gc. */
-
-Lisp_Object
-make_pure_string (const char *data,
- ptrdiff_t nchars, ptrdiff_t nbytes, bool multibyte)
-{
- Lisp_Object string;
- struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String);
- s->u.s.data = (unsigned char *) find_string_data_in_pure (data, nbytes);
- if (s->u.s.data == NULL)
- {
- s->u.s.data = pure_alloc (nbytes + 1, -1);
- memcpy (s->u.s.data, data, nbytes);
- s->u.s.data[nbytes] = '\0';
- }
- s->u.s.size = nchars;
- s->u.s.size_byte = multibyte ? nbytes : -1;
- s->u.s.intervals = NULL;
- XSETSTRING (string, s);
- return string;
-}
-
-/* Return a string allocated in pure space. Do not
- allocate the string data, just point to DATA. */
-
-Lisp_Object
-make_pure_c_string (const char *data, ptrdiff_t nchars)
-{
- Lisp_Object string;
- struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String);
- s->u.s.size = nchars;
- s->u.s.size_byte = -2;
- s->u.s.data = (unsigned char *) data;
- s->u.s.intervals = NULL;
- XSETSTRING (string, s);
- return string;
-}
-
-static Lisp_Object purecopy (Lisp_Object obj);
-
-/* Return a cons allocated from pure space. Give it pure copies
- of CAR as car and CDR as cdr. */
-
-Lisp_Object
-pure_cons (Lisp_Object car, Lisp_Object cdr)
-{
- Lisp_Object new;
- struct Lisp_Cons *p = pure_alloc (sizeof *p, Lisp_Cons);
- XSETCONS (new, p);
- XSETCAR (new, purecopy (car));
- XSETCDR (new, purecopy (cdr));
- return new;
-}
-
-
-/* Value is a float object with value NUM allocated from pure space. */
-
-static Lisp_Object
-make_pure_float (double num)
-{
- Lisp_Object new;
- struct Lisp_Float *p = pure_alloc (sizeof *p, Lisp_Float);
- XSETFLOAT (new, p);
- XFLOAT_INIT (new, num);
- return new;
-}
-
-/* Value is a bignum object with value VALUE allocated from pure
- space. */
-
-static Lisp_Object
-make_pure_bignum (Lisp_Object value)
-{
- mpz_t const *n = xbignum_val (value);
- size_t i, nlimbs = mpz_size (*n);
- size_t nbytes = nlimbs * sizeof (mp_limb_t);
- mp_limb_t *pure_limbs;
- mp_size_t new_size;
-
- struct Lisp_Bignum *b = pure_alloc (sizeof *b, Lisp_Vectorlike);
- XSETPVECTYPESIZE (b, PVEC_BIGNUM, 0, VECSIZE (struct Lisp_Bignum));
-
- int limb_alignment = alignof (mp_limb_t);
- pure_limbs = pure_alloc (nbytes, - limb_alignment);
- for (i = 0; i < nlimbs; ++i)
- pure_limbs[i] = mpz_getlimbn (*n, i);
-
- new_size = nlimbs;
- if (mpz_sgn (*n) < 0)
- new_size = -new_size;
-
- mpz_roinit_n (b->value, pure_limbs, new_size);
-
- return make_lisp_ptr (b, Lisp_Vectorlike);
-}
-
-/* Return a vector with room for LEN Lisp_Objects allocated from
- pure space. */
-
-static Lisp_Object
-make_pure_vector (ptrdiff_t len)
-{
- Lisp_Object new;
- size_t size = header_size + len * word_size;
- struct Lisp_Vector *p = pure_alloc (size, Lisp_Vectorlike);
- XSETVECTOR (new, p);
- XVECTOR (new)->header.size = len;
- return new;
-}
-
-/* Copy all contents and parameters of TABLE to a new table allocated
- from pure space, return the purified table. */
-static struct Lisp_Hash_Table *
-purecopy_hash_table (struct Lisp_Hash_Table *table)
-{
- eassert (table->weakness == Weak_None);
- eassert (table->purecopy);
-
- struct Lisp_Hash_Table *pure = pure_alloc (sizeof *pure, Lisp_Vectorlike);
- *pure = *table;
- pure->mutable = false;
-
- if (table->table_size > 0)
- {
- ptrdiff_t hash_bytes = table->table_size * sizeof *table->hash;
- pure->hash = pure_alloc (hash_bytes, -(int)sizeof *table->hash);
- memcpy (pure->hash, table->hash, hash_bytes);
-
- ptrdiff_t next_bytes = table->table_size * sizeof *table->next;
- pure->next = pure_alloc (next_bytes, -(int)sizeof *table->next);
- memcpy (pure->next, table->next, next_bytes);
-
- ptrdiff_t nvalues = table->table_size * 2;
- ptrdiff_t kv_bytes = nvalues * sizeof *table->key_and_value;
- pure->key_and_value = pure_alloc (kv_bytes,
- -(int)sizeof *table->key_and_value);
- for (ptrdiff_t i = 0; i < nvalues; i++)
- pure->key_and_value[i] = purecopy (table->key_and_value[i]);
-
- ptrdiff_t index_bytes = hash_table_index_size (table)
- * sizeof *table->index;
- pure->index = pure_alloc (index_bytes, -(int)sizeof *table->index);
- memcpy (pure->index, table->index, index_bytes);
- }
-
- return pure;
-}
-
-DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0,
- doc: /* Make a copy of object OBJ in pure storage.
-Recursively copies contents of vectors and cons cells.
-Does not copy symbols. Copies strings without text properties. */)
- (register Lisp_Object obj)
-{
- if (NILP (Vpurify_flag))
- return obj;
- else if (MARKERP (obj) || OVERLAYP (obj) || SYMBOLP (obj))
- /* Can't purify those. */
- return obj;
- else
- return purecopy (obj);
-}
-
-/* Pinned objects are marked before every GC cycle. */
-static struct pinned_object
-{
- Lisp_Object object;
- struct pinned_object *next;
-} *pinned_objects;
-
-static Lisp_Object
-purecopy (Lisp_Object obj)
-{
- if (FIXNUMP (obj)
- || (! SYMBOLP (obj) && PURE_P (XPNTR (obj)))
- || SUBRP (obj))
- return obj; /* Already pure. */
-
- if (STRINGP (obj) && XSTRING (obj)->u.s.intervals)
- message_with_string ("Dropping text-properties while making string `%s' pure",
- obj, true);
-
- if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */
- {
- Lisp_Object tmp = Fgethash (obj, Vpurify_flag, Qnil);
- if (!NILP (tmp))
- return tmp;
- }
-
- if (CONSP (obj))
- obj = pure_cons (XCAR (obj), XCDR (obj));
- else if (FLOATP (obj))
- obj = make_pure_float (XFLOAT_DATA (obj));
- else if (STRINGP (obj))
- obj = make_pure_string (SSDATA (obj), SCHARS (obj),
- SBYTES (obj),
- STRING_MULTIBYTE (obj));
- else if (HASH_TABLE_P (obj))
- {
- struct Lisp_Hash_Table *table = XHASH_TABLE (obj);
- /* Do not purify hash tables which haven't been defined with
- :purecopy as non-nil or are weak - they aren't guaranteed to
- not change. */
- if (table->weakness != Weak_None || !table->purecopy)
- {
- /* Instead, add the hash table to the list of pinned objects,
- so that it will be marked during GC. */
- struct pinned_object *o = xmalloc (sizeof *o);
- o->object = obj;
- o->next = pinned_objects;
- pinned_objects = o;
- return obj; /* Don't hash cons it. */
- }
-
- obj = make_lisp_hash_table (purecopy_hash_table (table));
- }
- else if (CLOSUREP (obj) || VECTORP (obj) || RECORDP (obj))
- {
- struct Lisp_Vector *objp = XVECTOR (obj);
- ptrdiff_t nbytes = vector_nbytes (objp);
- struct Lisp_Vector *vec = pure_alloc (nbytes, Lisp_Vectorlike);
- register ptrdiff_t i;
- ptrdiff_t size = ASIZE (obj);
- if (size & PSEUDOVECTOR_FLAG)
- size &= PSEUDOVECTOR_SIZE_MASK;
- memcpy (vec, objp, nbytes);
- for (i = 0; i < size; i++)
- vec->contents[i] = purecopy (vec->contents[i]);
- /* Byte code strings must be pinned. */
- if (CLOSUREP (obj) && size >= 2 && STRINGP (vec->contents[1])
- && !STRING_MULTIBYTE (vec->contents[1]))
- pin_string (vec->contents[1]);
- XSETVECTOR (obj, vec);
- }
- else if (BARE_SYMBOL_P (obj))
- {
- if (!XBARE_SYMBOL (obj)->u.s.pinned && !c_symbol_p (XBARE_SYMBOL (obj)))
- { /* We can't purify them, but they appear in many pure objects.
- Mark them as `pinned' so we know to mark them at every GC cycle. */
- XBARE_SYMBOL (obj)->u.s.pinned = true;
- symbol_block_pinned = symbol_block;
- }
- /* Don't hash-cons it. */
- return obj;
- }
- else if (BIGNUMP (obj))
- obj = make_pure_bignum (obj);
- else
- {
- AUTO_STRING (fmt, "Don't know how to purify: %S");
- Fsignal (Qerror, list1 (CALLN (Fformat, fmt, obj)));
- }
-
- if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */
- Fputhash (obj, obj, Vpurify_flag);
-
- return obj;
-}
-
-
/***********************************************************************
Protection from GC
@@ -6220,13 +5704,6 @@ compact_undo_list (Lisp_Object list)
return list;
}
-static void
-mark_pinned_objects (void)
-{
- for (struct pinned_object *pobj = pinned_objects; pobj; pobj = pobj->next)
- mark_object (pobj->object);
-}
-
#if defined HAVE_ANDROID && !defined (__clang__)
/* The Android gcc is broken and needs the following version of
@@ -6251,29 +5728,6 @@ android_make_lisp_symbol (struct Lisp_Symbol *sym)
#endif
static void
-mark_pinned_symbols (void)
-{
- struct symbol_block *sblk;
- int lim;
- struct Lisp_Symbol *sym, *end;
-
- if (symbol_block_pinned == symbol_block)
- lim = symbol_block_index;
- else
- lim = SYMBOL_BLOCK_SIZE;
-
- for (sblk = symbol_block_pinned; sblk; sblk = sblk->next)
- {
- sym = sblk->symbols, end = sym + lim;
- for (; sym < end; ++sym)
- if (sym->u.s.pinned)
- mark_object (make_lisp_symbol (sym));
-
- lim = SYMBOL_BLOCK_SIZE;
- }
-}
-
-static void
visit_vectorlike_root (struct gc_root_visitor visitor,
struct Lisp_Vector *ptr,
enum gc_root_type type)
@@ -6536,8 +5990,6 @@ garbage_collect (void)
struct gc_root_visitor visitor = { .visit = mark_object_root_visitor };
visit_static_gc_roots (visitor);
- mark_pinned_objects ();
- mark_pinned_symbols ();
mark_lread ();
mark_terminals ();
mark_kboards ();
@@ -6681,10 +6133,6 @@ where each entry has the form (NAME SIZE USED FREE), where:
keeps around for future allocations (maybe because it does not know how
to return them to the OS).
-However, if there was overflow in pure space, and Emacs was dumped
-using the \"unexec\" method, `garbage-collect' returns nil, because
-real GC can't be done.
-
Note that calling this function does not guarantee that absolutely all
unreachable objects will be garbage-collected. Emacs uses a
mark-and-sweep garbage collector, but is conservative when it comes to
@@ -7093,10 +6541,6 @@ process_mark_stack (ptrdiff_t base_sp)
{
Lisp_Object obj = mark_stack_pop ();
mark_obj: ;
- void *po = XPNTR (obj);
- if (PURE_P (po))
- continue;
-
#if GC_REMEMBER_LAST_MARKED
last_marked[last_marked_index++] = obj;
last_marked_index &= LAST_MARKED_SIZE - 1;
@@ -7106,6 +6550,7 @@ process_mark_stack (ptrdiff_t base_sp)
we encounter an object we know is bogus. This increases GC time
by ~80%. */
#if GC_CHECK_MARKED_OBJECTS
+ void *po = XPNTR (obj);
/* Check that the object pointed to by PO is known to be a Lisp
structure allocated from the heap. */
@@ -7339,11 +6784,13 @@ process_mark_stack (ptrdiff_t base_sp)
break;
default: emacs_abort ();
}
- if (!PURE_P (XSTRING (ptr->u.s.name)))
- set_string_marked (XSTRING (ptr->u.s.name));
+ set_string_marked (XSTRING (ptr->u.s.name));
mark_interval_tree (string_intervals (ptr->u.s.name));
/* Inner loop to mark next symbol in this bucket, if any. */
- po = ptr = ptr->u.s.next;
+ ptr = ptr->u.s.next;
+#if GC_CHECK_MARKED_OBJECTS
+ po = ptr;
+#endif
if (ptr)
goto nextsym;
}
@@ -7475,7 +6922,7 @@ survives_gc_p (Lisp_Object obj)
emacs_abort ();
}
- return survives_p || PURE_P (XPNTR (obj));
+ return survives_p;
}
@@ -8043,8 +7490,6 @@ init_alloc_once (void)
static void
init_alloc_once_for_pdumper (void)
{
- purebeg = PUREBEG;
- pure_size = PURESIZE;
mem_init ();
#ifdef DOUG_LEA_MALLOC
@@ -8098,7 +7543,7 @@ If this portion is smaller than `gc-cons-threshold', this is ignored. */);
Vgc_cons_percentage = make_float (0.1);
DEFVAR_INT ("pure-bytes-used", pure_bytes_used,
- doc: /* Number of bytes of shareable Lisp data allocated so far. */);
+ doc: /* No longer used. */);
DEFVAR_INT ("cons-cells-consed", cons_cells_consed,
doc: /* Number of cons cells that have been consed so far. */);
@@ -8124,9 +7569,11 @@ If this portion is smaller than `gc-cons-threshold', this is ignored. */);
DEFVAR_LISP ("purify-flag", Vpurify_flag,
doc: /* Non-nil means loading Lisp code in order to dump an executable.
-This means that certain objects should be allocated in shared (pure) space.
-It can also be set to a hash-table, in which case this table is used to
-do hash-consing of the objects allocated to pure space. */);
+This used to mean that certain objects should be allocated in shared
+(pure) space, but objects are not allocated in pure storage any more.
+This flag is still used in a few places, not to decide where objects are
+allocated, but to know if we're in the preload phase of Emacs's
+build. */);
DEFVAR_BOOL ("garbage-collection-messages", garbage_collection_messages,
doc: /* Non-nil means display messages at start and end of garbage collection. */);
@@ -8142,10 +7589,10 @@ do hash-consing of the objects allocated to pure space. */);
/* We build this in advance because if we wait until we need it, we might
not be able to allocate the memory to hold it. */
Vmemory_signal_data
- = pure_list (Qerror,
- build_pure_c_string ("Memory exhausted--use"
- " M-x save-some-buffers then"
- " exit and restart Emacs"));
+ = list (Qerror,
+ build_string ("Memory exhausted--use"
+ " M-x save-some-buffers then"
+ " exit and restart Emacs"));
DEFVAR_LISP ("memory-full", Vmemory_full,
doc: /* Non-nil means Emacs cannot get much more Lisp memory. */);
@@ -8195,7 +7642,6 @@ N should be nonnegative. */);
defsubr (&Smake_symbol);
defsubr (&Smake_marker);
defsubr (&Smake_finalizer);
- defsubr (&Spurecopy);
defsubr (&Sgarbage_collect);
defsubr (&Sgarbage_collect_maybe);
defsubr (&Smemory_info);
diff --git a/src/androidterm.c b/src/androidterm.c
index e0f66652300..3e367b391a8 100644
--- a/src/androidterm.c
+++ b/src/androidterm.c
@@ -6631,7 +6631,7 @@ android_term_init (void)
x_display_list = dpyinfo;
dpyinfo->name_list_element
- = Fcons (build_pure_c_string ("android"), Qnil);
+ = Fcons (build_string ("android"), Qnil);
color_file = Fexpand_file_name (build_string ("rgb.txt"),
Vdata_directory);
diff --git a/src/buffer.c b/src/buffer.c
index a4dc8b12093..40f7ec83d6b 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -4788,8 +4788,8 @@ init_buffer_once (void)
set_buffer_intervals (&buffer_defaults, NULL);
set_buffer_intervals (&buffer_local_symbols, NULL);
/* This is not strictly necessary, but let's make them initialized. */
- bset_name (&buffer_defaults, build_pure_c_string (" *buffer-defaults*"));
- bset_name (&buffer_local_symbols, build_pure_c_string (" *buffer-local-symbols*"));
+ bset_name (&buffer_defaults, build_string (" *buffer-defaults*"));
+ bset_name (&buffer_local_symbols, build_string (" *buffer-local-symbols*"));
BUFFER_PVEC_INIT (&buffer_defaults);
BUFFER_PVEC_INIT (&buffer_local_symbols);
@@ -4797,7 +4797,7 @@ init_buffer_once (void)
/* Must do these before making the first buffer! */
/* real setup is done in bindings.el */
- bset_mode_line_format (&buffer_defaults, build_pure_c_string ("%-"));
+ bset_mode_line_format (&buffer_defaults, build_string ("%-"));
bset_header_line_format (&buffer_defaults, Qnil);
bset_tab_line_format (&buffer_defaults, Qnil);
bset_abbrev_mode (&buffer_defaults, Qnil);
@@ -4865,7 +4865,7 @@ init_buffer_once (void)
current_buffer = 0;
pdumper_remember_lv_ptr_raw (&current_buffer, Lisp_Vectorlike);
- QSFundamental = build_pure_c_string ("Fundamental");
+ QSFundamental = build_string ("Fundamental");
DEFSYM (Qfundamental_mode, "fundamental-mode");
bset_major_mode (&buffer_defaults, Qfundamental_mode);
@@ -4879,10 +4879,10 @@ init_buffer_once (void)
/* Super-magic invisible buffer. */
Vprin1_to_string_buffer =
- Fget_buffer_create (build_pure_c_string (" prin1"), Qt);
+ Fget_buffer_create (build_string (" prin1"), Qt);
Vbuffer_alist = Qnil;
- Fset_buffer (Fget_buffer_create (build_pure_c_string ("*scratch*"), Qnil));
+ Fset_buffer (Fget_buffer_create (build_string ("*scratch*"), Qnil));
inhibit_modification_hooks = 0;
}
@@ -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)))
@@ -5106,9 +5065,9 @@ syms_of_buffer (void)
Qoverwrite_mode_binary));
Fput (Qprotected_field, Qerror_conditions,
- pure_list (Qprotected_field, Qerror));
+ list (Qprotected_field, Qerror));
Fput (Qprotected_field, Qerror_message,
- build_pure_c_string ("Attempt to modify a protected field"));
+ build_string ("Attempt to modify a protected field"));
DEFSYM (Qclone_indirect_buffer_hook, "clone-indirect-buffer-hook");
diff --git a/src/bytecode.c b/src/bytecode.c
index d62d7d067b1..ecea0c6df36 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -27,7 +27,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "keyboard.h"
#include "syntax.h"
#include "window.h"
-#include "puresize.h"
/* Define BYTE_CODE_SAFE true to enable some minor sanity checking,
useful for debugging the byte compiler. It defaults to false. */
@@ -1639,7 +1638,6 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
record_in_backtrace (Qsetcar, &TOP, 2);
wrong_type_argument (Qconsp, cell);
}
- CHECK_IMPURE (cell, XCONS (cell));
XSETCAR (cell, newval);
TOP = newval;
NEXT;
@@ -1654,7 +1652,6 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
record_in_backtrace (Qsetcdr, &TOP, 2);
wrong_type_argument (Qconsp, cell);
}
- CHECK_IMPURE (cell, XCONS (cell));
XSETCDR (cell, newval);
TOP = newval;
NEXT;
diff --git a/src/callint.c b/src/callint.c
index 9e9bcfd6b02..e0246e5d594 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -822,10 +822,10 @@ syms_of_callint (void)
callint_message = Qnil;
staticpro (&callint_message);
- preserved_fns = pure_list (intern_c_string ("region-beginning"),
- intern_c_string ("region-end"),
- intern_c_string ("point"),
- intern_c_string ("mark"));
+ preserved_fns = list (intern_c_string ("region-beginning"),
+ intern_c_string ("region-end"),
+ intern_c_string ("point"),
+ intern_c_string ("mark"));
staticpro (&preserved_fns);
DEFSYM (Qlist, "list");
diff --git a/src/callproc.c b/src/callproc.c
index 0b2a761cf59..33b0feaf266 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -2171,9 +2171,9 @@ See `setenv' and `getenv'. */);
Use this instead of calling `ctags' directly, as `ctags' may have been
renamed to comply with executable naming restrictions on the system. */);
#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
- Vctags_program_name = build_pure_c_string ("ctags");
+ Vctags_program_name = build_string ("ctags");
#else
- Vctags_program_name = build_pure_c_string ("libctags.so");
+ Vctags_program_name = build_string ("libctags.so");
#endif
DEFVAR_LISP ("etags-program-name", Vetags_program_name,
@@ -2181,9 +2181,9 @@ renamed to comply with executable naming restrictions on the system. */);
Use this instead of calling `etags' directly, as `etags' may have been
renamed to comply with executable naming restrictions on the system. */);
#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
- Vetags_program_name = build_pure_c_string ("etags");
+ Vetags_program_name = build_string ("etags");
#else
- Vetags_program_name = build_pure_c_string ("libetags.so");
+ Vetags_program_name = build_string ("libetags.so");
#endif
DEFVAR_LISP ("hexl-program-name", Vhexl_program_name,
@@ -2191,9 +2191,9 @@ renamed to comply with executable naming restrictions on the system. */);
Use this instead of calling `hexl' directly, as `hexl' may have been
renamed to comply with executable naming restrictions on the system. */);
#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
- Vhexl_program_name = build_pure_c_string ("hexl");
+ Vhexl_program_name = build_string ("hexl");
#else
- Vhexl_program_name = build_pure_c_string ("libhexl.so");
+ Vhexl_program_name = build_string ("libhexl.so");
#endif
DEFVAR_LISP ("emacsclient-program-name", Vemacsclient_program_name,
@@ -2202,9 +2202,9 @@ Use this instead of calling `emacsclient' directly, as `emacsclient'
may have been renamed to comply with executable naming restrictions on
the system. */);
#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
- Vemacsclient_program_name = build_pure_c_string ("emacsclient");
+ Vemacsclient_program_name = build_string ("emacsclient");
#else
- Vemacsclient_program_name = build_pure_c_string ("libemacsclient.so");
+ Vemacsclient_program_name = build_string ("libemacsclient.so");
#endif
DEFVAR_LISP ("movemail-program-name", Vmovemail_program_name,
@@ -2216,9 +2216,9 @@ the system. */);
use movemail from another source. */
#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY \
|| defined HAVE_MAILUTILS
- Vmovemail_program_name = build_pure_c_string ("movemail");
+ Vmovemail_program_name = build_string ("movemail");
#else
- Vmovemail_program_name = build_pure_c_string ("libmovemail.so");
+ Vmovemail_program_name = build_string ("libmovemail.so");
#endif
DEFVAR_LISP ("ebrowse-program-name", Vebrowse_program_name,
@@ -2227,9 +2227,9 @@ Use this instead of calling `ebrowse' directly, as `ebrowse'
may have been renamed to comply with executable naming restrictions on
the system. */);
#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
- Vebrowse_program_name = build_pure_c_string ("ebrowse");
+ Vebrowse_program_name = build_string ("ebrowse");
#else
- Vebrowse_program_name = build_pure_c_string ("libebrowse.so");
+ Vebrowse_program_name = build_string ("libebrowse.so");
#endif
DEFVAR_LISP ("rcs2log-program-name", Vrcs2log_program_name,
@@ -2238,9 +2238,9 @@ Use this instead of calling `rcs2log' directly, as `rcs2log'
may have been renamed to comply with executable naming restrictions on
the system. */);
#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
- Vrcs2log_program_name = build_pure_c_string ("rcs2log");
+ Vrcs2log_program_name = build_string ("rcs2log");
#else /* HAVE_ANDROID && !ANDROID_STUBIFY */
- Vrcs2log_program_name = build_pure_c_string ("librcs2log.so");
+ Vrcs2log_program_name = build_string ("librcs2log.so");
#endif /* !HAVE_ANDROID || ANDROID_STUBIFY */
defsubr (&Scall_process);
diff --git a/src/category.c b/src/category.c
index 2611d6419e8..297ba94c73d 100644
--- a/src/category.c
+++ b/src/category.c
@@ -51,7 +51,7 @@ hash_get_category_set (Lisp_Object table, Lisp_Object category_set)
if (NILP (XCHAR_TABLE (table)->extras[1]))
set_char_table_extras
(table, 1,
- make_hash_table (&hashtest_equal, DEFAULT_HASH_SIZE, Weak_None, false));
+ make_hash_table (&hashtest_equal, DEFAULT_HASH_SIZE, Weak_None));
struct Lisp_Hash_Table *h = XHASH_TABLE (XCHAR_TABLE (table)->extras[1]);
hash_hash_t hash;
ptrdiff_t i = hash_lookup_get_hash (h, category_set, &hash);
@@ -118,8 +118,6 @@ the current buffer's category table. */)
if (!NILP (CATEGORY_DOCSTRING (table, XFIXNAT (category))))
error ("Category `%c' is already defined", (int) XFIXNAT (category));
- if (!NILP (Vpurify_flag))
- docstring = Fpurecopy (docstring);
SET_CATEGORY_DOCSTRING (table, XFIXNAT (category), docstring);
return Qnil;
diff --git a/src/coding.c b/src/coding.c
index 6875d4af823..4f7cf23e96e 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -11766,7 +11766,7 @@ syms_of_coding (void)
Vcode_conversion_reused_workbuf = Qnil;
staticpro (&Vcode_conversion_workbuf_name);
- Vcode_conversion_workbuf_name = build_pure_c_string (" *code-conversion-work*");
+ Vcode_conversion_workbuf_name = build_string (" *code-conversion-work*");
reused_workbuf_in_use = false;
PDUMPER_REMEMBER_SCALAR (reused_workbuf_in_use);
@@ -11830,9 +11830,9 @@ syms_of_coding (void)
/* Error signaled when there's a problem with detecting a coding system. */
DEFSYM (Qcoding_system_error, "coding-system-error");
Fput (Qcoding_system_error, Qerror_conditions,
- pure_list (Qcoding_system_error, Qerror));
+ list (Qcoding_system_error, Qerror));
Fput (Qcoding_system_error, Qerror_message,
- build_pure_c_string ("Invalid coding system"));
+ build_string ("Invalid coding system"));
DEFSYM (Qtranslation_table, "translation-table");
Fput (Qtranslation_table, Qchar_table_extra_slots, make_fixnum (2));
@@ -12107,22 +12107,22 @@ used for encoding standard output and error streams. */);
DEFVAR_LISP ("eol-mnemonic-unix", eol_mnemonic_unix,
doc: /*
String displayed in mode line for UNIX-like (LF) end-of-line format. */);
- eol_mnemonic_unix = build_pure_c_string (":");
+ eol_mnemonic_unix = build_string (":");
DEFVAR_LISP ("eol-mnemonic-dos", eol_mnemonic_dos,
doc: /*
String displayed in mode line for DOS-like (CRLF) end-of-line format. */);
- eol_mnemonic_dos = build_pure_c_string ("\\");
+ eol_mnemonic_dos = build_string ("\\");
DEFVAR_LISP ("eol-mnemonic-mac", eol_mnemonic_mac,
doc: /*
String displayed in mode line for MAC-like (CR) end-of-line format. */);
- eol_mnemonic_mac = build_pure_c_string ("/");
+ eol_mnemonic_mac = build_string ("/");
DEFVAR_LISP ("eol-mnemonic-undecided", eol_mnemonic_undecided,
doc: /*
String displayed in mode line when end-of-line format is not yet determined. */);
- eol_mnemonic_undecided = build_pure_c_string (":");
+ eol_mnemonic_undecided = build_string (":");
DEFVAR_LISP ("enable-character-translation", Venable_character_translation,
doc: /*
@@ -12262,7 +12262,7 @@ internal character representation. */);
intern_c_string (":for-unibyte"),
args[coding_arg_for_unibyte] = Qt,
intern_c_string (":docstring"),
- (build_pure_c_string
+ (build_string
("Do no conversion.\n"
"\n"
"When you visit a file with this coding, the file is read into a\n"
@@ -12282,7 +12282,7 @@ internal character representation. */);
plist[8] = intern_c_string (":charset-list");
plist[9] = args[coding_arg_charset_list] = list1 (Qascii);
plist[11] = args[coding_arg_for_unibyte] = Qnil;
- plist[13] = build_pure_c_string ("No conversion on encoding, "
+ plist[13] = build_string ("No conversion on encoding, "
"automatic conversion on decoding.");
plist[15] = args[coding_arg_eol_type] = Qnil;
args[coding_arg_plist] = CALLMANY (Flist, plist);
diff --git a/src/comp.c b/src/comp.c
index ce59fdd80e3..2b2ac073214 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -31,7 +31,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <libgccjit.h>
#include <epaths.h>
-#include "puresize.h"
#include "window.h"
#include "dynlib.h"
#include "buffer.h"
@@ -469,7 +468,7 @@ load_gccjit_if_necessary (bool mandatory)
/* Increase this number to force a new Vcomp_abi_hash to be generated. */
-#define ABI_VERSION "6"
+#define ABI_VERSION "9"
/* Length of the hashes used for eln file naming. */
#define HASH_LENGTH 8
@@ -477,16 +476,13 @@ load_gccjit_if_necessary (bool mandatory)
/* C symbols emitted for the load relocation mechanism. */
#define CURRENT_THREAD_RELOC_SYM "current_thread_reloc"
#define F_SYMBOLS_WITH_POS_ENABLED_RELOC_SYM "f_symbols_with_pos_enabled_reloc"
-#define PURE_RELOC_SYM "pure_reloc"
#define DATA_RELOC_SYM "d_reloc"
-#define DATA_RELOC_IMPURE_SYM "d_reloc_imp"
#define DATA_RELOC_EPHEMERAL_SYM "d_reloc_eph"
#define FUNC_LINK_TABLE_SYM "freloc_link_table"
#define LINK_TABLE_HASH_SYM "freloc_hash"
#define COMP_UNIT_SYM "comp_unit"
#define TEXT_DATA_RELOC_SYM "text_data_reloc"
-#define TEXT_DATA_RELOC_IMPURE_SYM "text_data_reloc_imp"
#define TEXT_DATA_RELOC_EPHEMERAL_SYM "text_data_reloc_eph"
#define TEXT_OPTIM_QLY_SYM "text_optim_qly"
@@ -608,7 +604,6 @@ typedef struct {
gcc_jit_type *thread_state_ptr_type;
gcc_jit_rvalue *current_thread_ref;
/* Other globals. */
- gcc_jit_rvalue *pure_ptr;
#ifndef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast
/* This version of libgccjit has really limited support for casting
therefore this union will be used for the scope. */
@@ -640,7 +635,6 @@ typedef struct {
gcc_jit_function *setcar;
gcc_jit_function *setcdr;
gcc_jit_function *check_type;
- gcc_jit_function *check_impure;
gcc_jit_function *maybe_gc_or_quit;
Lisp_Object func_blocks_h; /* blk_name -> gcc_block. */
Lisp_Object exported_funcs_h; /* c-func-name -> gcc_jit_function *. */
@@ -648,8 +642,6 @@ typedef struct {
Lisp_Object emitter_dispatcher;
/* Synthesized struct holding data relocs. */
reloc_array_t data_relocs;
- /* Same as before but can't go in pure space. */
- reloc_array_t data_relocs_impure;
/* Same as before but content does not survive load phase. */
reloc_array_t data_relocs_ephemeral;
/* Global structure holding function relocations. */
@@ -659,7 +651,6 @@ typedef struct {
gcc_jit_lvalue *func_relocs_local;
gcc_jit_function *memcpy;
Lisp_Object d_default_idx;
- Lisp_Object d_impure_idx;
Lisp_Object d_ephemeral_idx;
} comp_t;
@@ -697,7 +688,6 @@ helper_sanitizer_assert (Lisp_Object, Lisp_Object);
static void *helper_link_table[] =
{ wrong_type_argument,
helper_PSEUDOVECTOR_TYPEP_XUNTAG,
- pure_write_error,
push_handler,
record_unwind_protect_excursion,
helper_unbind_n,
@@ -924,13 +914,6 @@ obj_to_reloc (Lisp_Object obj)
goto found;
}
- idx = Fgethash (obj, comp.d_impure_idx, Qnil);
- if (!NILP (idx))
- {
- reloc.array = comp.data_relocs_impure;
- goto found;
- }
-
idx = Fgethash (obj, comp.d_ephemeral_idx, Qnil);
if (!NILP (idx))
{
@@ -1972,28 +1955,6 @@ emit_XSETCDR (gcc_jit_rvalue *c, gcc_jit_rvalue *n)
NULL),
n);
}
-
-static gcc_jit_rvalue *
-emit_PURE_P (gcc_jit_rvalue *ptr)
-{
-
- emit_comment ("PURE_P");
-
- return
- gcc_jit_context_new_comparison (
- comp.ctxt,
- NULL,
- GCC_JIT_COMPARISON_LE,
- emit_binary_op (
- GCC_JIT_BINARY_OP_MINUS,
- comp.uintptr_type,
- ptr,
- comp.pure_ptr),
- gcc_jit_context_new_rvalue_from_int (comp.ctxt,
- comp.uintptr_type,
- PURESIZE));
-}
-
/*************************************/
/* Code emitted by LIMPLE statemes. */
@@ -2910,10 +2871,6 @@ declare_imported_data (void)
declare_imported_data_relocs (CALLNI (comp-ctxt-d-default, Vcomp_ctxt),
DATA_RELOC_SYM,
TEXT_DATA_RELOC_SYM);
- comp.data_relocs_impure =
- declare_imported_data_relocs (CALLNI (comp-ctxt-d-impure, Vcomp_ctxt),
- DATA_RELOC_IMPURE_SYM,
- TEXT_DATA_RELOC_IMPURE_SYM);
comp.data_relocs_ephemeral =
declare_imported_data_relocs (CALLNI (comp-ctxt-d-ephemeral, Vcomp_ctxt),
DATA_RELOC_EPHEMERAL_SYM,
@@ -2947,8 +2904,6 @@ declare_runtime_imported_funcs (void)
args[1] = comp.int_type;
ADD_IMPORTED (helper_PSEUDOVECTOR_TYPEP_XUNTAG, comp.bool_type, 2, args);
- ADD_IMPORTED (pure_write_error, comp.void_type, 1, NULL);
-
args[0] = comp.lisp_obj_type;
args[1] = comp.int_type;
ADD_IMPORTED (push_handler, comp.handler_ptr_type, 2, args);
@@ -3024,15 +2979,6 @@ emit_ctxt_code (void)
comp.bool_ptr_type,
F_SYMBOLS_WITH_POS_ENABLED_RELOC_SYM));
- comp.pure_ptr =
- gcc_jit_lvalue_as_rvalue (
- gcc_jit_context_new_global (
- comp.ctxt,
- NULL,
- GCC_JIT_GLOBAL_EXPORTED,
- comp.void_ptr_type,
- PURE_RELOC_SYM));
-
gcc_jit_context_new_global (
comp.ctxt,
NULL,
@@ -3694,19 +3640,6 @@ define_setcar_setcdr (void)
/* CHECK_CONS (cell); */
emit_CHECK_CONS (gcc_jit_param_as_rvalue (cell));
- /* CHECK_IMPURE (cell, XCONS (cell)); */
- gcc_jit_rvalue *args[] =
- { gcc_jit_param_as_rvalue (cell),
- emit_XCONS (gcc_jit_param_as_rvalue (cell)) };
-
- gcc_jit_block_add_eval (entry_block,
- NULL,
- gcc_jit_context_new_call (comp.ctxt,
- NULL,
- comp.check_impure,
- 2,
- args));
-
/* XSETCDR (cell, newel); */
if (!i)
emit_XSETCAR (gcc_jit_param_as_rvalue (cell),
@@ -4011,52 +3944,6 @@ static void define_SYMBOL_WITH_POS_SYM (void)
}
static void
-define_CHECK_IMPURE (void)
-{
- gcc_jit_param *param[] =
- { gcc_jit_context_new_param (comp.ctxt,
- NULL,
- comp.lisp_obj_type,
- "obj"),
- gcc_jit_context_new_param (comp.ctxt,
- NULL,
- comp.void_ptr_type,
- "ptr") };
- comp.check_impure =
- gcc_jit_context_new_function (comp.ctxt, NULL,
- GCC_JIT_FUNCTION_INTERNAL,
- comp.void_type,
- "CHECK_IMPURE",
- 2,
- param,
- 0);
-
- DECL_BLOCK (entry_block, comp.check_impure);
- DECL_BLOCK (err_block, comp.check_impure);
- DECL_BLOCK (ok_block, comp.check_impure);
-
- comp.block = entry_block;
- comp.func = comp.check_impure;
-
- emit_cond_jump (emit_PURE_P (gcc_jit_param_as_rvalue (param[0])), /* FIXME */
- err_block,
- ok_block);
- gcc_jit_block_end_with_void_return (ok_block, NULL);
-
- gcc_jit_rvalue *pure_write_error_arg =
- gcc_jit_param_as_rvalue (param[0]);
-
- comp.block = err_block;
- gcc_jit_block_add_eval (comp.block,
- NULL,
- emit_call (intern_c_string ("pure_write_error"),
- comp.void_type, 1,&pure_write_error_arg,
- false));
-
- gcc_jit_block_end_with_void_return (err_block, NULL);
-}
-
-static void
define_maybe_gc_or_quit (void)
{
@@ -4933,8 +4820,6 @@ DEFUN ("comp--compile-ctxt-to-file0", Fcomp__compile_ctxt_to_file0,
comp.d_default_idx =
CALLNI (comp-data-container-idx, CALLNI (comp-ctxt-d-default, Vcomp_ctxt));
- comp.d_impure_idx =
- CALLNI (comp-data-container-idx, CALLNI (comp-ctxt-d-impure, Vcomp_ctxt));
comp.d_ephemeral_idx =
CALLNI (comp-data-container-idx, CALLNI (comp-ctxt-d-ephemeral, Vcomp_ctxt));
@@ -4946,7 +4831,6 @@ DEFUN ("comp--compile-ctxt-to-file0", Fcomp__compile_ctxt_to_file0,
define_GET_SYMBOL_WITH_POSITION ();
define_CHECK_TYPE ();
define_SYMBOL_WITH_POS_SYM ();
- define_CHECK_IMPURE ();
define_bool_to_lisp_obj ();
define_setcar_setcdr ();
define_add1_sub1 ();
@@ -5194,10 +5078,10 @@ maybe_defer_native_compilation (Lisp_Object function_name,
Lisp_Object src =
concat2 (CALLNI (file-name-sans-extension, Vload_true_file_name),
- build_pure_c_string (".el"));
+ build_string (".el"));
if (NILP (Ffile_exists_p (src)))
{
- src = concat2 (src, build_pure_c_string (".gz"));
+ src = concat2 (src, build_string (".gz"));
if (NILP (Ffile_exists_p (src)))
return;
}
@@ -5267,25 +5151,20 @@ check_comp_unit_relocs (struct Lisp_Native_Comp_Unit *comp_u)
{
dynlib_handle_ptr handle = comp_u->handle;
Lisp_Object *data_relocs = dynlib_sym (handle, DATA_RELOC_SYM);
- Lisp_Object *data_imp_relocs = dynlib_sym (handle, DATA_RELOC_IMPURE_SYM);
EMACS_INT d_vec_len = XFIXNUM (Flength (comp_u->data_vec));
- for (ptrdiff_t i = 0; i < d_vec_len; i++)
- if (!EQ (data_relocs[i], AREF (comp_u->data_vec, i)))
- return false;
- d_vec_len = XFIXNUM (Flength (comp_u->data_impure_vec));
for (ptrdiff_t i = 0; i < d_vec_len; i++)
{
- Lisp_Object x = data_imp_relocs[i];
- if (EQ (x, Qlambda_fixup))
+ Lisp_Object x = data_relocs[i];
+ if (EQ (x, Q__lambda_fixup))
return false;
else if (NATIVE_COMP_FUNCTIONP (x))
{
if (NILP (Fgethash (x, comp_u->lambda_gc_guard_h, Qnil)))
return false;
}
- else if (!EQ (x, AREF (comp_u->data_impure_vec, i)))
+ else if (!EQ (x, AREF (comp_u->data_vec, i)))
return false;
}
return true;
@@ -5349,7 +5228,7 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump,
/* Always set data_imp_relocs pointer in the compilation unit (in can be
used in 'dump_do_dump_relocation'). */
- comp_u->data_imp_relocs = dynlib_sym (handle, DATA_RELOC_IMPURE_SYM);
+ comp_u->data_relocs = dynlib_sym (handle, DATA_RELOC_SYM);
if (!comp_u->loaded_once)
{
@@ -5357,16 +5236,12 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump,
dynlib_sym (handle, CURRENT_THREAD_RELOC_SYM);
bool **f_symbols_with_pos_enabled_reloc =
dynlib_sym (handle, F_SYMBOLS_WITH_POS_ENABLED_RELOC_SYM);
- void **pure_reloc = dynlib_sym (handle, PURE_RELOC_SYM);
- Lisp_Object *data_relocs = dynlib_sym (handle, DATA_RELOC_SYM);
- Lisp_Object *data_imp_relocs = comp_u->data_imp_relocs;
+ Lisp_Object *data_relocs = comp_u->data_relocs;
void **freloc_link_table = dynlib_sym (handle, FUNC_LINK_TABLE_SYM);
if (!(current_thread_reloc
&& f_symbols_with_pos_enabled_reloc
- && pure_reloc
&& data_relocs
- && data_imp_relocs
&& data_eph_relocs
&& freloc_link_table
&& top_level_run)
@@ -5376,7 +5251,6 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump,
*current_thread_reloc = &current_thread;
*f_symbols_with_pos_enabled_reloc = &symbols_with_pos_enabled;
- *pure_reloc = pure;
/* Imported functions. */
*freloc_link_table = freloc.link_table;
@@ -5387,21 +5261,11 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump,
comp_u->optimize_qualities =
load_static_obj (comp_u, TEXT_OPTIM_QLY_SYM);
comp_u->data_vec = load_static_obj (comp_u, TEXT_DATA_RELOC_SYM);
- comp_u->data_impure_vec =
- load_static_obj (comp_u, TEXT_DATA_RELOC_IMPURE_SYM);
-
- if (!NILP (Vpurify_flag))
- /* Non impure can be copied into pure space. */
- comp_u->data_vec = Fpurecopy (comp_u->data_vec);
}
EMACS_INT d_vec_len = XFIXNUM (Flength (comp_u->data_vec));
for (EMACS_INT i = 0; i < d_vec_len; i++)
data_relocs[i] = AREF (comp_u->data_vec, i);
-
- d_vec_len = XFIXNUM (Flength (comp_u->data_impure_vec));
- for (EMACS_INT i = 0; i < d_vec_len; i++)
- data_imp_relocs[i] = AREF (comp_u->data_impure_vec, i);
}
if (!loading_dump)
@@ -5557,7 +5421,7 @@ This gets called by top_level_run during the load phase. */)
eassert (NILP (Fgethash (c_name, cu->lambda_c_name_idx_h, Qnil)));
Fputhash (c_name, reloc_idx, cu->lambda_c_name_idx_h);
/* Do the real relocation fixup. */
- cu->data_imp_relocs[XFIXNUM (reloc_idx)] = tem;
+ cu->data_relocs[XFIXNUM (reloc_idx)] = tem;
return tem;
}
@@ -5739,7 +5603,6 @@ natively-compiled one. */);
/* Allocation classes. */
DEFSYM (Qd_default, "d-default");
- DEFSYM (Qd_impure, "d-impure");
DEFSYM (Qd_ephemeral, "d-ephemeral");
/* Others. */
@@ -5747,7 +5610,7 @@ natively-compiled one. */);
DEFSYM (Qfixnum, "fixnum");
DEFSYM (Qscratch, "scratch");
DEFSYM (Qlate, "late");
- DEFSYM (Qlambda_fixup, "lambda-fixup");
+ DEFSYM (Q__lambda_fixup, "--lambda-fixup");
DEFSYM (Qgccjit, "gccjit");
DEFSYM (Qcomp_subr_trampoline_install, "comp-subr-trampoline-install");
DEFSYM (Qnative_comp_warning_on_missing_source,
@@ -5756,48 +5619,48 @@ natively-compiled one. */);
/* To be signaled by the compiler. */
DEFSYM (Qnative_compiler_error, "native-compiler-error");
Fput (Qnative_compiler_error, Qerror_conditions,
- pure_list (Qnative_compiler_error, Qerror));
+ list (Qnative_compiler_error, Qerror));
Fput (Qnative_compiler_error, Qerror_message,
- build_pure_c_string ("Native compiler error"));
+ build_string ("Native compiler error"));
DEFSYM (Qnative_ice, "native-ice");
Fput (Qnative_ice, Qerror_conditions,
- pure_list (Qnative_ice, Qnative_compiler_error, Qerror));
+ list (Qnative_ice, Qnative_compiler_error, Qerror));
Fput (Qnative_ice, Qerror_message,
- build_pure_c_string ("Internal native compiler error"));
+ build_string ("Internal native compiler error"));
/* By the load machinery. */
DEFSYM (Qnative_lisp_load_failed, "native-lisp-load-failed");
Fput (Qnative_lisp_load_failed, Qerror_conditions,
- pure_list (Qnative_lisp_load_failed, Qerror));
+ list (Qnative_lisp_load_failed, Qerror));
Fput (Qnative_lisp_load_failed, Qerror_message,
- build_pure_c_string ("Native elisp load failed"));
+ build_string ("Native elisp load failed"));
DEFSYM (Qnative_lisp_wrong_reloc, "native-lisp-wrong-reloc");
Fput (Qnative_lisp_wrong_reloc, Qerror_conditions,
- pure_list (Qnative_lisp_wrong_reloc, Qnative_lisp_load_failed, Qerror));
+ list (Qnative_lisp_wrong_reloc, Qnative_lisp_load_failed, Qerror));
Fput (Qnative_lisp_wrong_reloc, Qerror_message,
- build_pure_c_string ("Primitive redefined or wrong relocation"));
+ build_string ("Primitive redefined or wrong relocation"));
DEFSYM (Qwrong_register_subr_call, "wrong-register-subr-call");
Fput (Qwrong_register_subr_call, Qerror_conditions,
- pure_list (Qwrong_register_subr_call, Qnative_lisp_load_failed, Qerror));
+ list (Qwrong_register_subr_call, Qnative_lisp_load_failed, Qerror));
Fput (Qwrong_register_subr_call, Qerror_message,
- build_pure_c_string ("comp--register-subr can only be called during "
- "native lisp load phase."));
+ build_string ("comp--register-subr can only be called during "
+ "native lisp load phase."));
DEFSYM (Qnative_lisp_file_inconsistent, "native-lisp-file-inconsistent");
Fput (Qnative_lisp_file_inconsistent, Qerror_conditions,
- pure_list (Qnative_lisp_file_inconsistent, Qnative_lisp_load_failed, Qerror));
+ list (Qnative_lisp_file_inconsistent, Qnative_lisp_load_failed, Qerror));
Fput (Qnative_lisp_file_inconsistent, Qerror_message,
- build_pure_c_string ("eln file inconsistent with current runtime "
- "configuration, please recompile"));
+ build_string ("eln file inconsistent with current runtime "
+ "configuration, please recompile"));
DEFSYM (Qcomp_sanitizer_error, "comp-sanitizer-error");
Fput (Qcomp_sanitizer_error, Qerror_conditions,
- pure_list (Qcomp_sanitizer_error, Qerror));
+ list (Qcomp_sanitizer_error, Qerror));
Fput (Qcomp_sanitizer_error, Qerror_message,
- build_pure_c_string ("Native code sanitizer runtime error"));
+ build_string ("Native code sanitizer runtime error"));
DEFSYM (Qnative__compile_async, "native--compile-async");
diff --git a/src/comp.h b/src/comp.h
index 8525f8ee44f..b4edc4ad371 100644
--- a/src/comp.h
+++ b/src/comp.h
@@ -35,17 +35,15 @@ struct Lisp_Native_Comp_Unit
/* Guard anonymous lambdas against Garbage Collection and serve
sanity checks. */
Lisp_Object lambda_gc_guard_h;
- /* Hash c_name -> d_reloc_imp index. */
+ /* Hash c_name -> d_reloc index. */
Lisp_Object lambda_c_name_idx_h;
/* Hash doc-idx -> function documentation. */
Lisp_Object data_fdoc_v;
- /* Analogous to the constant vector but per compilation unit. */
+ /* Analogous to the constant vector but per compilation unit. Must be
+ last. */
Lisp_Object data_vec;
- /* 'data_impure_vec' must be last (see allocate_native_comp_unit).
- Same as data_vec but for data that cannot be moved to pure space. */
- Lisp_Object data_impure_vec;
/* STUFFS WE DO NOT DUMP!! */
- Lisp_Object *data_imp_relocs;
+ Lisp_Object *data_relocs;
bool loaded_once;
bool load_ongoing;
dynlib_handle_ptr handle;
diff --git a/src/conf_post.h b/src/conf_post.h
index 29d14bf672b..6be76d5481a 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -155,43 +155,10 @@ You lose; /* Emacs for DOS must be compiled with DJGPP */
#define emacs_raise(sig) msdos_fatal_signal (sig)
-/* DATA_START is needed by vm-limit.c and unexcoff.c. */
+/* DATA_START is needed by vm-limit.c. */
#define DATA_START (&etext + 1)
-
-/* Define one of these for easier conditionals. */
-#ifdef HAVE_X_WINDOWS
-/* We need a little extra space, see ../../lisp/loadup.el and the
- commentary below, in the non-X branch. The 140KB number was
- measured on GNU/Linux and on MS-Windows. */
-#define SYSTEM_PURESIZE_EXTRA (-170000+140000)
-#else
-/* We need a little extra space, see ../../lisp/loadup.el.
- As of 20091024, DOS-specific files use up 62KB of pure space. But
- overall, we end up wasting 130KB of pure space, because
- BASE_PURESIZE starts at 1.47MB, while we need only 1.3MB (including
- non-DOS specific files and load history; the latter is about 55K,
- but depends on the depth of the top-level Emacs directory in the
- directory tree). Given the unknown policy of different DPMI
- hosts regarding loading of untouched pages, I'm not going to risk
- enlarging Emacs footprint by another 100+ KBytes. */
-#define SYSTEM_PURESIZE_EXTRA (-170000+90000)
-#endif
#endif /* MSDOS */
-/* macOS / GNUstep need a bit more pure memory. Of the existing knobs,
- SYSTEM_PURESIZE_EXTRA seems like the least likely to cause problems. */
-#ifdef HAVE_NS
-#if defined NS_IMPL_GNUSTEP
-# define SYSTEM_PURESIZE_EXTRA 30000
-#elif defined DARWIN_OS
-# define SYSTEM_PURESIZE_EXTRA 200000
-#endif
-#endif
-
-#ifdef CYGWIN
-#define SYSTEM_PURESIZE_EXTRA 50000
-#endif
-
#if defined HAVE_NTGUI && !defined DebPrint
# ifdef EMACSDEBUG
extern void _DebPrint (const char *fmt, ...);
diff --git a/src/data.c b/src/data.c
index dcaa5756ebe..5fcdda1b6e8 100644
--- a/src/data.c
+++ b/src/data.c
@@ -27,7 +27,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "lisp.h"
#include "bignum.h"
-#include "puresize.h"
#include "character.h"
#include "buffer.h"
#include "keyboard.h"
@@ -136,12 +135,6 @@ wrong_type_argument (Lisp_Object predicate, Lisp_Object value)
}
void
-pure_write_error (Lisp_Object obj)
-{
- xsignal2 (Qerror, build_string ("Attempt to modify read-only object"), obj);
-}
-
-void
args_out_of_range (Lisp_Object a1, Lisp_Object a2)
{
xsignal2 (Qargs_out_of_range, a1, a2);
@@ -695,7 +688,6 @@ DEFUN ("setcar", Fsetcar, Ssetcar, 2, 2, 0,
(register Lisp_Object cell, Lisp_Object newcar)
{
CHECK_CONS (cell);
- CHECK_IMPURE (cell, XCONS (cell));
XSETCAR (cell, newcar);
return newcar;
}
@@ -705,7 +697,6 @@ DEFUN ("setcdr", Fsetcdr, Ssetcdr, 2, 2, 0,
(register Lisp_Object cell, Lisp_Object newcdr)
{
CHECK_CONS (cell);
- CHECK_IMPURE (cell, XCONS (cell));
XSETCDR (cell, newcdr);
return newcdr;
}
@@ -1003,10 +994,6 @@ The return value is undefined. */)
(register Lisp_Object symbol, Lisp_Object definition, Lisp_Object docstring)
{
CHECK_SYMBOL (symbol);
- if (!NILP (Vpurify_flag)
- /* If `definition' is a keymap, immutable (and copying) is wrong. */
- && !KEYMAPP (definition))
- definition = Fpurecopy (definition);
defalias (symbol, definition);
@@ -2596,7 +2583,6 @@ bool-vector. IDX starts at 0. */)
if (VECTORP (array))
{
- CHECK_IMPURE (array, XVECTOR (array));
if (idxval < 0 || idxval >= ASIZE (array))
args_out_of_range (array, idx);
ASET (array, idxval, newelt);
@@ -2614,14 +2600,12 @@ bool-vector. IDX starts at 0. */)
}
else if (RECORDP (array))
{
- CHECK_IMPURE (array, XVECTOR (array));
if (idxval < 0 || idxval >= PVSIZE (array))
args_out_of_range (array, idx);
ASET (array, idxval, newelt);
}
else /* STRINGP */
{
- CHECK_IMPURE (array, XSTRING (array));
if (idxval < 0 || idxval >= SCHARS (array))
args_out_of_range (array, idx);
CHECK_CHARACTER (newelt);
@@ -4081,7 +4065,7 @@ syms_of_data (void)
DEFSYM (Qaref, "aref");
DEFSYM (Qaset, "aset");
- error_tail = pure_cons (Qerror, Qnil);
+ error_tail = Fcons (Qerror, Qnil);
/* ERROR is used as a signaler for random errors for which nothing else is
right. */
@@ -4089,14 +4073,14 @@ syms_of_data (void)
Fput (Qerror, Qerror_conditions,
error_tail);
Fput (Qerror, Qerror_message,
- build_pure_c_string ("error"));
+ build_string ("error"));
#define PUT_ERROR(sym, tail, msg) \
- Fput (sym, Qerror_conditions, pure_cons (sym, tail)); \
- Fput (sym, Qerror_message, build_pure_c_string (msg))
+ Fput (sym, Qerror_conditions, Fcons (sym, tail)); \
+ Fput (sym, Qerror_message, build_string (msg))
PUT_ERROR (Qquit, Qnil, "Quit");
- PUT_ERROR (Qminibuffer_quit, pure_cons (Qquit, Qnil), "Quit");
+ PUT_ERROR (Qminibuffer_quit, Fcons (Qquit, Qnil), "Quit");
PUT_ERROR (Quser_error, error_tail, "");
PUT_ERROR (Qwrong_length_argument, error_tail, "Wrong length argument");
@@ -4125,14 +4109,14 @@ syms_of_data (void)
PUT_ERROR (Qno_catch, error_tail, "No catch for tag");
PUT_ERROR (Qend_of_file, error_tail, "End of file during parsing");
- arith_tail = pure_cons (Qarith_error, error_tail);
+ arith_tail = Fcons (Qarith_error, error_tail);
Fput (Qarith_error, Qerror_conditions, arith_tail);
- Fput (Qarith_error, Qerror_message, build_pure_c_string ("Arithmetic error"));
+ Fput (Qarith_error, Qerror_message, build_string ("Arithmetic error"));
PUT_ERROR (Qbeginning_of_buffer, error_tail, "Beginning of buffer");
PUT_ERROR (Qend_of_buffer, error_tail, "End of buffer");
PUT_ERROR (Qbuffer_read_only, error_tail, "Buffer is read-only");
- PUT_ERROR (Qtext_read_only, pure_cons (Qbuffer_read_only, error_tail),
+ PUT_ERROR (Qtext_read_only, Fcons (Qbuffer_read_only, error_tail),
"Text is read-only");
PUT_ERROR (Qinhibited_interaction, error_tail,
"User interaction while inhibited");
@@ -4155,10 +4139,10 @@ syms_of_data (void)
PUT_ERROR (Qunderflow_error, Fcons (Qrange_error, arith_tail),
"Arithmetic underflow error");
- recursion_tail = pure_cons (Qrecursion_error, error_tail);
+ recursion_tail = Fcons (Qrecursion_error, error_tail);
Fput (Qrecursion_error, Qerror_conditions, recursion_tail);
- Fput (Qrecursion_error, Qerror_message, build_pure_c_string
- ("Excessive recursive calling error"));
+ Fput (Qrecursion_error, Qerror_message,
+ build_string ("Excessive recursive calling error"));
PUT_ERROR (Qexcessive_lisp_nesting, recursion_tail,
"Lisp nesting exceeds `max-lisp-eval-depth'");
diff --git a/src/dbusbind.c b/src/dbusbind.c
index d98009f68b4..5f89122eaf7 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -1909,7 +1909,7 @@ syms_of_dbusbind (void)
Fput (Qdbus_error, Qerror_conditions,
list2 (Qdbus_error, Qerror));
Fput (Qdbus_error, Qerror_message,
- build_pure_c_string ("D-Bus error"));
+ build_string ("D-Bus error"));
DEFSYM (QD_Bus, "D-Bus");
/* Lisp symbols of the system and session buses. */
@@ -1959,7 +1959,7 @@ syms_of_dbusbind (void)
Vdbus_compiled_version,
doc: /* The version of D-Bus Emacs is compiled against. */);
#ifdef DBUS_VERSION_STRING
- Vdbus_compiled_version = build_pure_c_string (DBUS_VERSION_STRING);
+ Vdbus_compiled_version = build_string (DBUS_VERSION_STRING);
#else
Vdbus_compiled_version = Qnil;
#endif
diff --git a/src/deps.mk b/src/deps.mk
index 4acce04c04b..e2c786f8fb0 100644
--- a/src/deps.mk
+++ b/src/deps.mk
@@ -92,7 +92,7 @@ editfns.o: editfns.c window.h buffer.h systime.h $(INTERVALS_H) character.h \
emacs.o: emacs.c commands.h systty.h syssignal.h blockinput.h process.h \
termhooks.h buffer.h atimer.h systime.h $(INTERVALS_H) lisp.h $(config_h) \
globals.h ../lib/unistd.h window.h dispextern.h keyboard.h keymap.h \
- frame.h coding.h gnutls.h msdos.h dosfns.h unexec.h
+ frame.h coding.h gnutls.h msdos.h dosfns.h
fileio.o: fileio.c window.h buffer.h systime.h $(INTERVALS_H) character.h \
coding.h msdos.h blockinput.h atimer.h lisp.h $(config_h) frame.h \
commands.h globals.h ../lib/unistd.h
@@ -132,12 +132,11 @@ insdel.o: insdel.c window.h buffer.h $(INTERVALS_H) blockinput.h character.h \
keyboard.o: keyboard.c termchar.h termhooks.h termopts.h buffer.h character.h \
commands.h frame.h window.h macros.h disptab.h keyboard.h syssignal.h \
systime.h syntax.h $(INTERVALS_H) blockinput.h atimer.h composite.h \
- xterm.h puresize.h msdos.h keymap.h w32term.h nsterm.h nsgui.h coding.h \
+ xterm.h msdos.h keymap.h w32term.h nsterm.h nsgui.h coding.h \
process.h ../lib/unistd.h gnutls.h lisp.h globals.h $(config_h)
keymap.o: keymap.c buffer.h commands.h keyboard.h termhooks.h blockinput.h \
- atimer.h systime.h puresize.h character.h charset.h $(INTERVALS_H) \
+ atimer.h systime.h character.h charset.h $(INTERVALS_H) \
keymap.h window.h coding.h frame.h lisp.h globals.h $(config_h)
-lastfile.o: lastfile.c $(config_h)
macros.o: macros.c window.h buffer.h commands.h macros.h keyboard.h msdos.h \
dispextern.h lisp.h globals.h $(config_h) systime.h coding.h composite.h
gmalloc.o: gmalloc.c $(config_h)
@@ -202,14 +201,6 @@ terminfo.o: terminfo.c tparam.h lisp.h globals.h $(config_h)
tparam.o: tparam.c tparam.h lisp.h $(config_h)
undo.o: undo.c buffer.h commands.h window.h dispextern.h msdos.h \
lisp.h globals.h $(config_h)
-unexaix.o: unexaix.c lisp.h unexec.h $(config_h)
-unexcw.o: unexcw.c lisp.h unexec.h $(config_h)
-unexcoff.o: unexcoff.c lisp.h unexec.h $(config_h)
-unexelf.o: unexelf.c unexec.h ../lib/unistd.h $(config_h)
-unexhp9k800.o: unexhp9k800.c unexec.h $(config_h)
-unexmacosx.o: unexmacosx.c unexec.h $(config_h)
-unexsol.o: unexsol.c lisp.h unexec.h $(config_h)
-unexw32.o: unexw32.c unexec.h $(config_h)
w16select.o: w16select.c dispextern.h frame.h blockinput.h atimer.h systime.h \
msdos.h buffer.h charset.h coding.h composite.h lisp.h $(config_h)
widget.o: widget.c xterm.h frame.h dispextern.h widgetprv.h \
@@ -267,12 +258,12 @@ xsettings.o: xterm.h xsettings.h lisp.h frame.h termhooks.h $(config_h) \
atimer.h termopts.h globals.h
## The files of Lisp proper.
-alloc.o: alloc.c process.h frame.h window.h buffer.h puresize.h syssignal.h \
+alloc.o: alloc.c process.h frame.h window.h buffer.h syssignal.h \
keyboard.h blockinput.h atimer.h systime.h character.h lisp.h $(config_h) \
$(INTERVALS_H) termhooks.h gnutls.h coding.h ../lib/unistd.h globals.h
bytecode.o: bytecode.c buffer.h syntax.h character.h window.h dispextern.h \
lisp.h globals.h $(config_h) msdos.h
-data.o: data.c buffer.h puresize.h character.h syssignal.h keyboard.h frame.h \
+data.o: data.c buffer.h character.h syssignal.h keyboard.h frame.h \
termhooks.h systime.h coding.h composite.h dispextern.h font.h ccl.h \
lisp.h globals.h $(config_h) msdos.h
eval.o: eval.c commands.h keyboard.h blockinput.h atimer.h systime.h frame.h \
@@ -295,7 +286,7 @@ lread.o: lread.c commands.h keyboard.h buffer.h epaths.h character.h \
composite.o: composite.c composite.h buffer.h character.h coding.h font.h \
ccl.h frame.h termhooks.h $(INTERVALS_H) window.h \
lisp.h globals.h $(config_h)
-intervals.o: intervals.c buffer.h $(INTERVALS_H) keyboard.h puresize.h \
+intervals.o: intervals.c buffer.h $(INTERVALS_H) keyboard.h \
keymap.h lisp.h globals.h $(config_h) systime.h coding.h
textprop.o: textprop.c buffer.h window.h $(INTERVALS_H) \
lisp.h globals.h $(config_h)
diff --git a/src/doc.c b/src/doc.c
index 09e099efcdb..6bc34550d31 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -549,7 +549,6 @@ the same file name is found in the `doc-directory'. */)
int i = ARRAYELTS (buildobj);
while (0 <= --i)
Vbuild_files = Fcons (build_string (buildobj[i]), Vbuild_files);
- Vbuild_files = Fpurecopy (Vbuild_files);
}
doc_fd fd = doc_open (name, O_RDONLY, 0);
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 196b8a57754..0a67433ec70 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -1709,44 +1709,44 @@ syms_of_module (void)
{
staticpro (&Vmodule_refs_hash);
Vmodule_refs_hash
- = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None, false);
+ = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None);
DEFSYM (Qmodule_load_failed, "module-load-failed");
Fput (Qmodule_load_failed, Qerror_conditions,
- pure_list (Qmodule_load_failed, Qerror));
+ list (Qmodule_load_failed, Qerror));
Fput (Qmodule_load_failed, Qerror_message,
- build_pure_c_string ("Module load failed"));
+ build_string ("Module load failed"));
DEFSYM (Qmodule_open_failed, "module-open-failed");
Fput (Qmodule_open_failed, Qerror_conditions,
- pure_list (Qmodule_open_failed, Qmodule_load_failed, Qerror));
+ list (Qmodule_open_failed, Qmodule_load_failed, Qerror));
Fput (Qmodule_open_failed, Qerror_message,
- build_pure_c_string ("Module could not be opened"));
+ build_string ("Module could not be opened"));
DEFSYM (Qmodule_not_gpl_compatible, "module-not-gpl-compatible");
Fput (Qmodule_not_gpl_compatible, Qerror_conditions,
- pure_list (Qmodule_not_gpl_compatible, Qmodule_load_failed, Qerror));
+ list (Qmodule_not_gpl_compatible, Qmodule_load_failed, Qerror));
Fput (Qmodule_not_gpl_compatible, Qerror_message,
- build_pure_c_string ("Module is not GPL compatible"));
+ build_string ("Module is not GPL compatible"));
DEFSYM (Qmissing_module_init_function, "missing-module-init-function");
Fput (Qmissing_module_init_function, Qerror_conditions,
- pure_list (Qmissing_module_init_function, Qmodule_load_failed,
- Qerror));
+ list (Qmissing_module_init_function, Qmodule_load_failed,
+ Qerror));
Fput (Qmissing_module_init_function, Qerror_message,
- build_pure_c_string ("Module does not export an "
+ build_string ("Module does not export an "
"initialization function"));
DEFSYM (Qmodule_init_failed, "module-init-failed");
Fput (Qmodule_init_failed, Qerror_conditions,
- pure_list (Qmodule_init_failed, Qmodule_load_failed, Qerror));
+ list (Qmodule_init_failed, Qmodule_load_failed, Qerror));
Fput (Qmodule_init_failed, Qerror_message,
- build_pure_c_string ("Module initialization failed"));
+ build_string ("Module initialization failed"));
DEFSYM (Qinvalid_arity, "invalid-arity");
- Fput (Qinvalid_arity, Qerror_conditions, pure_list (Qinvalid_arity, Qerror));
+ Fput (Qinvalid_arity, Qerror_conditions, list (Qinvalid_arity, Qerror));
Fput (Qinvalid_arity, Qerror_message,
- build_pure_c_string ("Invalid function arity"));
+ build_string ("Invalid function arity"));
DEFSYM (Qmodule_function_p, "module-function-p");
DEFSYM (Qunicode_string_p, "unicode-string-p");
diff --git a/src/emacs.c b/src/emacs.c
index 6f005c64351..f0281044c9e 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -110,11 +110,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "composite.h"
#include "dispextern.h"
#include "regex-emacs.h"
-#include "sheap.h"
#include "syntax.h"
#include "sysselect.h"
#include "systime.h"
-#include "puresize.h"
#include "getpagesize.h"
#include "gnutls.h"
@@ -196,11 +194,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 +905,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,75 +1303,37 @@ 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)
+ if (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
- temacs and only if we are going to dump with unexec. */
- bool use_dynamic_heap = true;
- if (temacs)
- {
- char *temacs_str = NULL, *p;
- for (p = argv[0]; (p = strstr (p, "temacs")) != NULL; p++)
- temacs_str = p;
- if (temacs_str != NULL
- && (temacs_str == argv[0] || IS_DIRECTORY_SEP (temacs_str[-1])))
- {
- /* Note that gflags are set at this point only if we have been
- called with the --temacs=METHOD option. We assume here that
- temacs is always called that way, otherwise the functions
- that rely on gflags, like will_dump_with_pdumper_p below,
- will not do their job. */
- use_dynamic_heap = will_dump_with_pdumper_p ();
- }
- }
- init_heap (use_dynamic_heap);
+ happens. */
+ init_heap ();
initial_cmdline = GetCommandLine ();
#endif
#if defined WINDOWSNT || defined HAVE_NTGUI
@@ -1438,25 +1385,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);
@@ -1621,7 +1555,7 @@ android_emacs_init (int argc, char **argv, char *dump_file)
emacs_backtrace (-1);
-#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
+#if !defined SYSTEM_MALLOC
/* Arrange to get warning messages as memory fills up. */
memory_warnings (0, malloc_warning);
@@ -1629,7 +1563,7 @@ android_emacs_init (int argc, char **argv, char *dump_file)
Also call realloc and free for consistency. */
free (realloc (malloc (4), 4));
-#endif /* not SYSTEM_MALLOC and not HYBRID_MALLOC */
+#endif /* not SYSTEM_MALLOC */
#ifdef MSDOS
set_binary_mode (STDIN_FILENO, O_BINARY);
@@ -1638,10 +1572,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))
{
@@ -1938,11 +1869,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
}
#if defined HAVE_PTHREAD && !defined SYSTEM_MALLOC \
- && !defined DOUG_LEA_MALLOC && !defined HYBRID_MALLOC
+ && !defined DOUG_LEA_MALLOC
/* Do not make gmalloc thread-safe when creating bootstrap-emacs, as
that causes an infinite recursive loop with FreeBSD. See
- Bug#14569. The part of this bug involving Cygwin is no longer
- relevant, now that Cygwin defines HYBRID_MALLOC. */
+ Bug#14569. */
if (!noninteractive || !will_dump_p ())
malloc_enable_thread ();
#endif
@@ -3159,117 +3089,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
fixup_locale (void)
@@ -3568,10 +3387,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/eval.c b/src/eval.c
index cf05d3baea4..666d49f03fe 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -817,8 +817,6 @@ value. */)
XSYMBOL (symbol)->u.s.declared_special = true;
if (!NILP (doc))
{
- if (!NILP (Vpurify_flag))
- doc = Fpurecopy (doc);
Fput (symbol, Qvariable_documentation, doc);
}
LOADHIST_ATTACH (symbol);
@@ -967,8 +965,6 @@ More specifically, behaves like (defconst SYM 'INITVALUE DOCSTRING). */)
CHECK_SYMBOL (sym);
Lisp_Object tem = initvalue;
Finternal__define_uninitialized_variable (sym, docstring);
- if (!NILP (Vpurify_flag))
- tem = Fpurecopy (tem);
Fset_default (sym, tem); /* FIXME: set-default-toplevel-value? */
Fput (sym, Qrisky_local_variable, Qt); /* FIXME: Why? */
return sym;
@@ -1992,8 +1988,7 @@ signal_error (const char *s, Lisp_Object arg)
xsignal (Qerror, Fcons (build_string (s), arg));
}
-/* Simplified version of 'define-error' that works with pure
- objects. */
+/* Simplified version of 'define-error'. */
void
define_error (Lisp_Object name, const char *message, Lisp_Object parent)
@@ -2004,8 +1999,8 @@ define_error (Lisp_Object name, const char *message, Lisp_Object parent)
eassert (CONSP (parent_conditions));
eassert (!NILP (Fmemq (parent, parent_conditions)));
eassert (NILP (Fmemq (name, parent_conditions)));
- Fput (name, Qerror_conditions, pure_cons (name, parent_conditions));
- Fput (name, Qerror_message, build_pure_c_string (message));
+ Fput (name, Qerror_conditions, Fcons (name, parent_conditions));
+ Fput (name, Qerror_message, build_string (message));
}
/* Use this for arithmetic overflow, e.g., when an integer result is
@@ -2321,12 +2316,6 @@ this does nothing and returns nil. */)
&& !AUTOLOADP (XSYMBOL (function)->u.s.function))
return Qnil;
- if (!NILP (Vpurify_flag) && BASE_EQ (docstring, make_fixnum (0)))
- /* `read1' in lread.c has found the docstring starting with "\
- and assumed the docstring will be provided by Snarf-documentation, so it
- passed us 0 instead. But that leads to accidental sharing in purecopy's
- hash-consing, so we use a (hopefully) unique integer instead. */
- docstring = make_ufixnum (XHASH (function));
return Fdefalias (function,
list5 (Qautoload, file, docstring, interactive, type),
Qnil);
@@ -4480,7 +4469,7 @@ alist of active lexical bindings. */);
also use something like Fcons (Qnil, Qnil), but json.c treats any
cons cell as error data, so use an uninterned symbol instead. */
Qcatch_all_memory_full
- = Fmake_symbol (build_pure_c_string ("catch-all-memory-full"));
+ = Fmake_symbol (build_string ("catch-all-memory-full"));
staticpro (&list_of_t);
list_of_t = list1 (Qt);
diff --git a/src/fileio.c b/src/fileio.c
index cb131264492..1832a4c7759 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -6671,39 +6671,39 @@ behaves as if file names were encoded in `utf-8'. */);
DEFSYM (Qcar_less_than_car, "car-less-than-car");
Fput (Qfile_error, Qerror_conditions,
- Fpurecopy (list2 (Qfile_error, Qerror)));
+ list2 (Qfile_error, Qerror));
Fput (Qfile_error, Qerror_message,
- build_pure_c_string ("File error"));
+ build_string ("File error"));
Fput (Qfile_already_exists, Qerror_conditions,
- Fpurecopy (list3 (Qfile_already_exists, Qfile_error, Qerror)));
+ list3 (Qfile_already_exists, Qfile_error, Qerror));
Fput (Qfile_already_exists, Qerror_message,
- build_pure_c_string ("File already exists"));
+ build_string ("File already exists"));
Fput (Qfile_date_error, Qerror_conditions,
- Fpurecopy (list3 (Qfile_date_error, Qfile_error, Qerror)));
+ list3 (Qfile_date_error, Qfile_error, Qerror));
Fput (Qfile_date_error, Qerror_message,
- build_pure_c_string ("Cannot set file date"));
+ build_string ("Cannot set file date"));
Fput (Qfile_missing, Qerror_conditions,
- Fpurecopy (list3 (Qfile_missing, Qfile_error, Qerror)));
+ list3 (Qfile_missing, Qfile_error, Qerror));
Fput (Qfile_missing, Qerror_message,
- build_pure_c_string ("File is missing"));
+ build_string ("File is missing"));
Fput (Qpermission_denied, Qerror_conditions,
- Fpurecopy (list3 (Qpermission_denied, Qfile_error, Qerror)));
+ list3 (Qpermission_denied, Qfile_error, Qerror));
Fput (Qpermission_denied, Qerror_message,
- build_pure_c_string ("Cannot access file or directory"));
+ build_string ("Cannot access file or directory"));
Fput (Qfile_notify_error, Qerror_conditions,
- Fpurecopy (list3 (Qfile_notify_error, Qfile_error, Qerror)));
+ list3 (Qfile_notify_error, Qfile_error, Qerror));
Fput (Qfile_notify_error, Qerror_message,
- build_pure_c_string ("File notification error"));
+ build_string ("File notification error"));
Fput (Qremote_file_error, Qerror_conditions,
- Fpurecopy (list3 (Qremote_file_error, Qfile_error, Qerror)));
+ list3 (Qremote_file_error, Qfile_error, Qerror));
Fput (Qremote_file_error, Qerror_message,
- build_pure_c_string ("Remote file error"));
+ build_string ("Remote file error"));
DEFVAR_LISP ("file-name-handler-alist", Vfile_name_handler_alist,
doc: /* Alist of elements (REGEXP . HANDLER) for file names handled specially.
diff --git a/src/firstfile.c b/src/firstfile.c
deleted file mode 100644
index 1cd190a631b..00000000000
--- a/src/firstfile.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Mark beginning of data space to dump as pure, for GNU Emacs.
- Copyright (C) 1997, 2001-2025 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-
-#include <config.h>
-
-#ifdef WINDOWSNT
-/* See comments in lastfile.c. */
-char my_begdata[] = "Beginning of Emacs initialized data";
-char my_begbss[1]; /* Do not initialize this variable. */
-static char _my_begbss[1];
-char * my_begbss_static = _my_begbss;
-
-/* Add a dummy reference to ensure emacs.o is linked in. */
-extern int main (int, char **);
-int (*dummy_main_reference) (int, char **) = main;
-#endif
diff --git a/src/fns.c b/src/fns.c
index 081ed2b9f51..ec1a39fada7 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -36,7 +36,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "buffer.h"
#include "intervals.h"
#include "window.h"
-#include "puresize.h"
#include "gnutls.h"
#ifdef HAVE_TREE_SITTER
@@ -3277,7 +3276,6 @@ ARRAY is a vector, string, char-table, or bool-vector. */)
size = SCHARS (array);
if (size != 0)
{
- CHECK_IMPURE (array, XSTRING (array));
unsigned char str[MAX_MULTIBYTE_LENGTH];
int len;
if (STRING_MULTIBYTE (array))
@@ -3320,7 +3318,6 @@ removes all text properties. This may change its length. */)
Qnil, string);
if (len != 0 || STRING_MULTIBYTE (string))
{
- CHECK_IMPURE (string, XSTRING (string));
memset (SDATA (string), 0, len);
STRING_SET_CHARS (string, len);
STRING_SET_UNIBYTE (string);
@@ -4862,15 +4859,11 @@ static const hash_idx_t empty_hash_index_vector[] = {-1};
Give the table initial capacity SIZE, 0 <= SIZE <= MOST_POSITIVE_FIXNUM.
- WEAK specifies the weakness of the table.
-
- If PURECOPY is non-nil, the table can be copied to pure storage via
- `purecopy' when Emacs is being dumped. Such tables can no longer be
- changed after purecopy. */
+ WEAK specifies the weakness of the table. */
Lisp_Object
make_hash_table (const struct hash_table_test *test, EMACS_INT size,
- hash_table_weakness_t weak, bool purecopy)
+ hash_table_weakness_t weak)
{
eassert (SYMBOLP (test->name));
eassert (0 <= size && size <= min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX));
@@ -4916,7 +4909,6 @@ make_hash_table (const struct hash_table_test *test, EMACS_INT size,
}
h->next_weak = NULL;
- h->purecopy = purecopy;
h->mutable = true;
return make_lisp_hash_table (h);
}
@@ -5031,11 +5023,6 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket));
set_hash_index_slot (h, start_of_bucket, i);
}
-
-#ifdef ENABLE_CHECKING
- if (HASH_TABLE_P (Vpurify_flag) && XHASH_TABLE (Vpurify_flag) == h)
- message ("Growing hash table to: %"pD"d", new_size);
-#endif
}
}
@@ -5140,7 +5127,6 @@ check_mutable_hash_table (Lisp_Object obj, struct Lisp_Hash_Table *h)
{
if (!h->mutable)
signal_error ("hash table test modifies table", obj);
- eassert (!PURE_P (h));
}
/* Put an entry into hash table H that associates KEY with VALUE.
@@ -5752,13 +5738,8 @@ key, value, one of key or value, or both key and value, depending on
WEAK. WEAK t is equivalent to `key-and-value'. Default value of WEAK
is nil.
-:purecopy PURECOPY -- If PURECOPY is non-nil, the table can be copied
-to pure storage when Emacs is being dumped, making the contents of the
-table read only. Any further changes to purified tables will result
-in an error.
-
-The keywords arguments :rehash-threshold and :rehash-size are obsolete
-and ignored.
+The keywords arguments :rehash-threshold, :rehash-size, and :purecopy
+are obsolete and ignored.
usage: (make-hash-table &rest KEYWORD-ARGS) */)
(ptrdiff_t nargs, Lisp_Object *args)
@@ -5766,7 +5747,6 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
Lisp_Object test_arg = Qnil;
Lisp_Object weakness_arg = Qnil;
Lisp_Object size_arg = Qnil;
- Lisp_Object purecopy_arg = Qnil;
if (nargs & 1)
error ("Odd number of arguments");
@@ -5780,9 +5760,8 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
weakness_arg = arg;
else if (BASE_EQ (kw, QCsize))
size_arg = arg;
- else if (BASE_EQ (kw, QCpurecopy))
- purecopy_arg = arg;
- else if (BASE_EQ (kw, QCrehash_threshold) || BASE_EQ (kw, QCrehash_size))
+ else if (BASE_EQ (kw, QCrehash_threshold) || BASE_EQ (kw, QCrehash_size)
+ || BASE_EQ (kw, QCpurecopy))
; /* ignore obsolete keyword arguments */
else
signal_error ("Invalid keyword argument", kw);
@@ -5798,8 +5777,6 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
else
test = get_hash_table_user_test (test_arg);
- bool purecopy = !NILP (purecopy_arg);
-
EMACS_INT size;
if (NILP (size_arg))
size = DEFAULT_HASH_SIZE;
@@ -5822,7 +5799,7 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
else
signal_error ("Invalid hash table weakness", weakness_arg);
- return make_hash_table (test, size, weak, purecopy);
+ return make_hash_table (test, size, weak);
}
diff --git a/src/fontset.c b/src/fontset.c
index c0086b49257..f71730d8a2e 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -2174,7 +2174,7 @@ syms_of_fontset (void)
set_fontset_id (Vdefault_fontset, make_fixnum (0));
set_fontset_name
(Vdefault_fontset,
- build_pure_c_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default"));
+ build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default"));
ASET (Vfontset_table, 0, Vdefault_fontset);
next_fontset_id = 1;
PDUMPER_REMEMBER_SCALAR (next_fontset_id);
@@ -2232,7 +2232,7 @@ alternate fontnames (if any) are tried instead. */);
doc: /* Alist of fontset names vs the aliases. */);
Vfontset_alias_alist
= list1 (Fcons (FONTSET_NAME (Vdefault_fontset),
- build_pure_c_string ("fontset-default")));
+ build_string ("fontset-default")));
DEFVAR_LISP ("vertical-centering-font-regexp",
Vvertical_centering_font_regexp,
diff --git a/src/frame.c b/src/frame.c
index 4f3c1efc4a7..cac9b0a4acd 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1078,7 +1078,7 @@ make_frame (bool mini_p)
rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f);
fset_face_hash_table
- (f, make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None, false));
+ (f, make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None));
if (mini_p)
{
@@ -1242,7 +1242,7 @@ make_initial_frame (void)
Vframe_list = Fcons (frame, Vframe_list);
tty_frame_count = 1;
- fset_name (f, build_pure_c_string ("F1"));
+ fset_name (f, build_string ("F1"));
SET_FRAME_VISIBLE (f, true);
diff --git a/src/gmalloc.c b/src/gmalloc.c
index fe6a0412a9b..18b993f78d0 100644
--- a/src/gmalloc.c
+++ b/src/gmalloc.c
@@ -21,7 +21,7 @@ License along with this library. If not, see <https://www.gnu.org/licenses/>.
#include <config.h>
-#if defined HAVE_PTHREAD && !defined HYBRID_MALLOC
+#if defined HAVE_PTHREAD
#define USE_PTHREAD
#endif
@@ -57,13 +57,6 @@ extern void *(*__morecore) (ptrdiff_t);
extern void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void);
#endif /* !defined HAVE_MALLOC_H || glibc >= 2.24 */
-/* If HYBRID_MALLOC is defined, then temacs will use malloc,
- realloc... as defined in this file (and renamed gmalloc,
- grealloc... via the macros that follow). The dumped emacs,
- however, will use the system malloc, realloc.... In other source
- files, malloc, realloc... are renamed hybrid_malloc,
- hybrid_realloc... via macros in lisp.h. hybrid_malloc and
- friends are wrapper functions defined later in this file. */
#undef malloc
#undef realloc
#undef calloc
@@ -76,19 +69,11 @@ extern void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void);
#define free gfree
#define malloc_info gmalloc_info
-#ifdef HYBRID_MALLOC
-# include "sheap.h"
-#endif
-
#ifdef __cplusplus
extern "C"
{
#endif
-#ifdef HYBRID_MALLOC
-#define extern static
-#endif
-
/* Allocate SIZE bytes of memory. */
extern void *malloc (size_t size) ATTRIBUTE_MALLOC_SIZE ((1));
/* Re-allocate the previously allocated block
@@ -327,8 +312,6 @@ void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void);
void (*__MALLOC_HOOK_VOLATILE __after_morecore_hook) (void);
void *(*__morecore) (ptrdiff_t);
-#ifndef HYBRID_MALLOC
-
/* Pointer to the base of the first block. */
char *_heapbase;
@@ -350,11 +333,9 @@ size_t _bytes_free;
/* Are you experienced? */
int __malloc_initialized;
-#endif /* HYBRID_MALLOC */
-
/* Number of extra blocks to get each time we ask for more core.
This reduces the frequency of calling `(*__morecore)'. */
-#if defined DOUG_LEA_MALLOC || defined HYBRID_MALLOC || defined SYSTEM_MALLOC
+#if defined DOUG_LEA_MALLOC || defined SYSTEM_MALLOC
static
#endif
size_t __malloc_extra_blocks;
@@ -917,7 +898,7 @@ malloc (size_t size)
return (hook ? hook : _malloc_internal) (size);
}
-#if !(defined (_LIBC) || defined (HYBRID_MALLOC))
+#if !(defined (_LIBC))
/* On some ANSI C systems, some libc functions call _malloc, _free
and _realloc. Make them use the GNU functions. */
@@ -969,11 +950,8 @@ License along with this library. If not, see <https://www.gnu.org/licenses/>.
/* Debugging hook for free. */
static void (*__MALLOC_HOOK_VOLATILE gfree_hook) (void *);
-#ifndef HYBRID_MALLOC
-
/* List of blocks allocated by aligned_alloc. */
struct alignlist *_aligned_blocks = NULL;
-#endif
/* Return memory to the heap.
Like `_free_internal' but don't lock mutex. */
@@ -1244,7 +1222,6 @@ free (void *ptr)
_free_internal (ptr);
}
-#ifndef HYBRID_MALLOC
/* Define the `cfree' alias for `free'. */
#ifdef weak_alias
weak_alias (free, cfree)
@@ -1255,7 +1232,6 @@ cfree (void *ptr)
free (ptr);
}
#endif
-#endif
/* Change the size of a block allocated by `malloc'.
Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2025 Free
Software Foundation, Inc.
@@ -1495,12 +1471,6 @@ extern void *__sbrk (ptrdiff_t increment);
static void *
gdefault_morecore (ptrdiff_t increment)
{
-#ifdef HYBRID_MALLOC
- if (!definitely_will_not_unexec_p ())
- {
- return bss_sbrk (increment);
- }
-#endif
#ifdef HAVE_SBRK
void *result = (void *) __sbrk (increment);
if (result != (void *) -1)
@@ -1610,7 +1580,6 @@ aligned_alloc (size_t alignment, size_t size)
}
/* Note that memalign and posix_memalign are not used in Emacs. */
-#ifndef HYBRID_MALLOC
/* An obsolete alias for aligned_alloc, for any old libraries that use
this alias. */
@@ -1620,8 +1589,6 @@ memalign (size_t alignment, size_t size)
return aligned_alloc (alignment, size);
}
-/* If HYBRID_MALLOC is defined, we may want to use the system
- posix_memalign below. */
int
posix_memalign (void **memptr, size_t alignment, size_t size)
{
@@ -1640,7 +1607,6 @@ posix_memalign (void **memptr, size_t alignment, size_t size)
return 0;
}
-#endif
/* Allocate memory on a page boundary.
Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2025 Free
@@ -1662,18 +1628,16 @@ License along with this library. If not, see <https://www.gnu.org/licenses/>.
The author may be reached (Email) at the address mike@ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
-#ifndef HYBRID_MALLOC
-
-# ifndef HAVE_MALLOC_H
+#ifndef HAVE_MALLOC_H
/* Allocate SIZE bytes on a page boundary. */
extern void *valloc (size_t);
-# endif
+#endif
-# if defined _SC_PAGESIZE || !defined HAVE_GETPAGESIZE
-# include "getpagesize.h"
-# elif !defined getpagesize
+#if defined _SC_PAGESIZE || !defined HAVE_GETPAGESIZE
+# include "getpagesize.h"
+#elif !defined getpagesize
extern int getpagesize (void);
-# endif
+#endif
static size_t pagesize;
@@ -1685,7 +1649,6 @@ valloc (size_t size)
return aligned_alloc (pagesize, size);
}
-#endif /* HYBRID_MALLOC */
#undef malloc
#undef realloc
@@ -1693,116 +1656,6 @@ valloc (size_t size)
#undef aligned_alloc
#undef free
-#ifdef HYBRID_MALLOC
-
-/* Assuming PTR was allocated via the hybrid malloc, return true if
- PTR was allocated via gmalloc, not the system malloc. Also, return
- true if _heaplimit is zero; this can happen temporarily when
- gmalloc calls itself for internal use, and in that case PTR is
- already known to be allocated via gmalloc. */
-
-static bool
-allocated_via_gmalloc (void *ptr)
-{
- if (!__malloc_initialized)
- return false;
- size_t block = BLOCK (ptr);
- size_t blockmax = _heaplimit - 1;
- return block <= blockmax && _heapinfo[block].busy.type != 0;
-}
-
-/* See the comments near the beginning of this file for explanations
- of the following functions. */
-
-void *
-hybrid_malloc (size_t size)
-{
- if (definitely_will_not_unexec_p ())
- return malloc (size);
- return gmalloc (size);
-}
-
-void *
-hybrid_calloc (size_t nmemb, size_t size)
-{
- if (definitely_will_not_unexec_p ())
- return calloc (nmemb, size);
- return gcalloc (nmemb, size);
-}
-
-static void
-hybrid_free_1 (void *ptr)
-{
- if (allocated_via_gmalloc (ptr))
- gfree (ptr);
- else
- free (ptr);
-}
-
-void
-hybrid_free (void *ptr)
-{
- /* Stolen from Gnulib, to make sure we preserve errno. */
-#if defined __GNUC__ && !defined __clang__
- int err[2];
- err[0] = errno;
- err[1] = errno;
- errno = 0;
- hybrid_free_1 (ptr);
- errno = err[errno == 0];
-#else
- int err = errno;
- hybrid_free_1 (ptr);
- errno = err;
-#endif
-}
-
-#if defined HAVE_ALIGNED_ALLOC || defined HAVE_POSIX_MEMALIGN
-void *
-hybrid_aligned_alloc (size_t alignment, size_t size)
-{
- if (!definitely_will_not_unexec_p ())
- return galigned_alloc (alignment, size);
- /* The following is copied from alloc.c */
-#ifdef HAVE_ALIGNED_ALLOC
- return aligned_alloc (alignment, size);
-#else /* HAVE_POSIX_MEMALIGN */
- void *p;
- return posix_memalign (&p, alignment, size) == 0 ? p : 0;
-#endif
-}
-#endif
-
-void *
-hybrid_realloc (void *ptr, size_t size)
-{
- void *result;
- int type;
- size_t block, oldsize;
-
- if (!ptr)
- return hybrid_malloc (size);
- if (!allocated_via_gmalloc (ptr))
- return realloc (ptr, size);
- if (!definitely_will_not_unexec_p ())
- return grealloc (ptr, size);
-
- /* The dumped emacs is trying to realloc storage allocated before
- dumping via gmalloc. Allocate new space and copy the data. Do
- not bother with gfree (ptr), as that would just waste time. */
- block = BLOCK (ptr);
- type = _heapinfo[block].busy.type;
- oldsize =
- type < 0 ? _heapinfo[block].busy.info.size * BLOCKSIZE
- : (size_t) 1 << type;
- result = malloc (size);
- if (result)
- return memcpy (result, ptr, min (oldsize, size));
- return result;
-}
-
-#else /* ! HYBRID_MALLOC */
-
void *
malloc (size_t size)
{
@@ -1833,8 +1686,6 @@ realloc (void *ptr, size_t size)
return grealloc (ptr, size);
}
-#endif /* HYBRID_MALLOC */
-
#ifdef GC_MCHECK
/* Standard debugging hooks for `malloc'.
diff --git a/src/haikufns.c b/src/haikufns.c
index 22e82048fc4..6490a22bd01 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -3300,7 +3300,7 @@ invalid color. */);
int len = sprintf (cairo_version, "%d.%d.%d",
CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
CAIRO_VERSION_MICRO);
- Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
+ Vcairo_version_string = make_specified_string (cairo_version, len, len, false);
}
#endif
diff --git a/src/image.c b/src/image.c
index 0d7e77164b6..dfab0d76edb 100644
--- a/src/image.c
+++ b/src/image.c
@@ -6225,7 +6225,7 @@ xpm_make_color_table_h (void (**put_func) (Lisp_Object, const char *, int,
{
*put_func = xpm_put_color_table_h;
*get_func = xpm_get_color_table_h;
- return make_hash_table (&hashtest_equal, DEFAULT_HASH_SIZE, Weak_None, false);
+ return make_hash_table (&hashtest_equal, DEFAULT_HASH_SIZE, Weak_None);
}
static void
diff --git a/src/intervals.c b/src/intervals.c
index b937c947ab0..a6c7d938df7 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -44,7 +44,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "lisp.h"
#include "intervals.h"
#include "buffer.h"
-#include "puresize.h"
#include "keymap.h"
/* Test for membership, allowing for t (actually any non-cons) to mean the
@@ -101,7 +100,6 @@ create_root_interval (Lisp_Object parent)
}
else
{
- CHECK_IMPURE (parent, XSTRING (parent));
new->total_length = SCHARS (parent);
eassert (TOTAL_LENGTH (new) >= 0);
set_string_intervals (parent, new);
diff --git a/src/json.c b/src/json.c
index 4e156658ef7..f438d191bde 100644
--- a/src/json.c
+++ b/src/json.c
@@ -1564,7 +1564,7 @@ json_parse_object (struct json_parser *parser)
case json_object_hashtable:
{
EMACS_INT value = (parser->object_workspace_current - first) / 2;
- result = make_hash_table (&hashtest_equal, value, Weak_None, false);
+ result = make_hash_table (&hashtest_equal, value, Weak_None);
struct Lisp_Hash_Table *h = XHASH_TABLE (result);
for (size_t i = first; i < parser->object_workspace_current; i += 2)
{
diff --git a/src/keyboard.c b/src/keyboard.c
index 850b5e06480..2d8c45c05ee 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -12840,14 +12840,14 @@ syms_of_keyboard (void)
pending_funcalls = Qnil;
staticpro (&pending_funcalls);
- Vlispy_mouse_stem = build_pure_c_string ("mouse");
+ Vlispy_mouse_stem = build_string ("mouse");
staticpro (&Vlispy_mouse_stem);
- regular_top_level_message = build_pure_c_string ("Back to top level");
+ regular_top_level_message = build_string ("Back to top level");
staticpro (&regular_top_level_message);
#ifdef HAVE_STACK_OVERFLOW_HANDLING
recover_top_level_message
- = build_pure_c_string ("Re-entering top level after C stack overflow");
+ = build_string ("Re-entering top level after C stack overflow");
staticpro (&recover_top_level_message);
#endif
DEFVAR_LISP ("internal--top-level-message", Vinternal__top_level_message,
diff --git a/src/keymap.c b/src/keymap.c
index 99291e72b3f..5691b34c40d 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -50,7 +50,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "keyboard.h"
#include "termhooks.h"
#include "blockinput.h"
-#include "puresize.h"
#include "intervals.h"
#include "keymap.h"
#include "window.h"
@@ -121,8 +120,6 @@ in case you use it as a menu with `x-popup-menu'. */)
{
if (!NILP (string))
{
- if (!NILP (Vpurify_flag))
- string = Fpurecopy (string);
return list2 (Qkeymap, string);
}
return list1 (Qkeymap);
@@ -301,7 +298,6 @@ Return PARENT. PARENT should be nil or another keymap. */)
If we came to the end, add the parent in PREV. */
if (!CONSP (list) || KEYMAPP (list))
{
- CHECK_IMPURE (prev, XCONS (prev));
XSETCDR (prev, parent);
return parent;
}
@@ -744,7 +740,7 @@ store_in_keymap (Lisp_Object keymap, register Lisp_Object idx,
/* If we are preparing to dump, and DEF is a menu element
with a menu item indicator, copy it to ensure it is not pure. */
- if (CONSP (def) && PURE_P (XCONS (def))
+ if (CONSP (def)
&& (EQ (XCAR (def), Qmenu_item) || STRINGP (XCAR (def))))
def = Fcons (XCAR (def), XCDR (def));
@@ -788,7 +784,6 @@ store_in_keymap (Lisp_Object keymap, register Lisp_Object idx,
{
if (FIXNATP (idx) && XFIXNAT (idx) < ASIZE (elt))
{
- CHECK_IMPURE (elt, XVECTOR (elt));
ASET (elt, XFIXNAT (idx), def);
return def;
}
@@ -846,7 +841,6 @@ store_in_keymap (Lisp_Object keymap, register Lisp_Object idx,
}
else if (EQ (idx, XCAR (elt)))
{
- CHECK_IMPURE (elt, XCONS (elt));
if (remove)
/* Remove the element. */
insertion_point = Fdelq (elt, insertion_point);
@@ -901,7 +895,6 @@ store_in_keymap (Lisp_Object keymap, register Lisp_Object idx,
}
else
elt = Fcons (idx, def);
- CHECK_IMPURE (insertion_point, XCONS (insertion_point));
XSETCDR (insertion_point, Fcons (elt, XCDR (insertion_point)));
}
}
@@ -3357,12 +3350,12 @@ syms_of_keymap (void)
current_global_map = Qnil;
staticpro (&current_global_map);
- exclude_keys = pure_list
- (pure_cons (build_pure_c_string ("DEL"), build_pure_c_string ("\\d")),
- pure_cons (build_pure_c_string ("TAB"), build_pure_c_string ("\\t")),
- pure_cons (build_pure_c_string ("RET"), build_pure_c_string ("\\r")),
- pure_cons (build_pure_c_string ("ESC"), build_pure_c_string ("\\e")),
- pure_cons (build_pure_c_string ("SPC"), build_pure_c_string (" ")));
+ exclude_keys = list
+ (Fcons (build_string ("DEL"), build_string ("\\d")),
+ Fcons (build_string ("TAB"), build_string ("\\t")),
+ Fcons (build_string ("RET"), build_string ("\\r")),
+ Fcons (build_string ("ESC"), build_string ("\\e")),
+ Fcons (build_string ("SPC"), build_string (" ")));
staticpro (&exclude_keys);
DEFVAR_LISP ("minibuffer-local-map", Vminibuffer_local_map,
@@ -3424,13 +3417,13 @@ that describe key bindings. That is why the default is nil. */);
DEFSYM (Qmode_line, "mode-line");
staticpro (&Vmouse_events);
- Vmouse_events = pure_list (Qmenu_bar, Qtab_bar, Qtool_bar,
- Qtab_line, Qheader_line, Qmode_line,
- intern_c_string ("mouse-1"),
- intern_c_string ("mouse-2"),
- intern_c_string ("mouse-3"),
- intern_c_string ("mouse-4"),
- intern_c_string ("mouse-5"));
+ Vmouse_events = list (Qmenu_bar, Qtab_bar, Qtool_bar, Qtab_line,
+ Qheader_line, Qmode_line,
+ intern_c_string ("mouse-1"),
+ intern_c_string ("mouse-2"),
+ intern_c_string ("mouse-3"),
+ intern_c_string ("mouse-4"),
+ intern_c_string ("mouse-5"));
/* Keymap used for minibuffers when doing completion. */
/* Keymap used for minibuffers when doing completion and require a match. */
diff --git a/src/lastfile.c b/src/lastfile.c
deleted file mode 100644
index a31a30553ca..00000000000
--- a/src/lastfile.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Mark end of data space to dump as pure, for GNU Emacs.
- Copyright (C) 1985, 2001-2025 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-
-/* How this works:
-
- Fdump_emacs dumps everything up to my_edata as text space (pure).
-
- The files of Emacs are written so as to have no initialized
- data that can ever need to be altered except at the first startup.
- This is so that those words can be dumped as shareable text.
-
- It is not possible to exercise such control over library files.
- So it is necessary to refrain from making their data areas shared.
- Therefore, this file is loaded following all the files of Emacs
- but before library files.
- As a result, the symbol my_edata indicates the point
- in data space between data coming from Emacs and data
- coming from libraries.
-*/
-
-#include <config.h>
-
-#include "lisp.h"
-
-#if ((!defined SYSTEM_MALLOC && !defined HYBRID_MALLOC) \
- || 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..5595038f7c7 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);
@@ -837,9 +796,6 @@ struct Lisp_Symbol
special (with `defvar' etc), and shouldn't be lexically bound. */
bool_bf declared_special : 1;
- /* True if pointed to from purespace and hence can't be GC'd. */
- bool_bf pinned : 1;
-
/* The symbol's name, as a Lisp string. */
Lisp_Object name;
@@ -2666,13 +2622,9 @@ struct Lisp_Hash_Table
/* Hash table test (only used when frozen in dump) */
ENUM_BF (hash_table_std_test_t) frozen_test : 2;
- /* True if the table can be purecopied. The table cannot be
- changed afterwards. */
- bool_bf purecopy : 1;
-
/* True if the table is mutable. Ordinarily tables are mutable, but
- pure tables are not, and while a table is being mutated it is
- immutable for recursive attempts to mutate it. */
+ some tables are not: while a table is being mutated it is immutable
+ for recursive attempts to mutate it. */
bool_bf mutable : 1;
/* Next weak hash table if this is a weak hash table. The head of
@@ -3445,14 +3397,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.
@@ -4299,7 +4247,7 @@ extern char *extract_data_from_object (Lisp_Object, ptrdiff_t *, ptrdiff_t *);
EMACS_UINT hash_string (char const *, ptrdiff_t);
EMACS_UINT sxhash (Lisp_Object);
Lisp_Object make_hash_table (const struct hash_table_test *, EMACS_INT,
- hash_table_weakness_t, bool);
+ hash_table_weakness_t);
Lisp_Object hash_table_weakness_symbol (hash_table_weakness_t weak);
ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object);
ptrdiff_t hash_lookup_get_hash (struct Lisp_Hash_Table *h, Lisp_Object key,
@@ -4474,8 +4422,6 @@ extern void parse_str_as_multibyte (const unsigned char *, ptrdiff_t,
/* Defined in alloc.c. */
extern intptr_t garbage_collection_inhibited;
-extern void *my_heap_start (void);
-extern void check_pure_size (void);
unsigned char *resize_string_data (Lisp_Object, ptrdiff_t, int, int);
extern void malloc_warning (const char *);
extern AVOID memory_full (size_t);
@@ -4483,11 +4429,9 @@ extern AVOID buffer_memory_full (ptrdiff_t);
extern bool survives_gc_p (Lisp_Object);
extern void mark_object (Lisp_Object);
extern void mark_objects (Lisp_Object *, ptrdiff_t);
-#if defined REL_ALLOC && !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
+#if defined REL_ALLOC && !defined SYSTEM_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);
@@ -4540,11 +4484,8 @@ extern Lisp_Object list4 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
extern Lisp_Object list5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object);
extern Lisp_Object listn (ptrdiff_t, Lisp_Object, ...);
-extern Lisp_Object pure_listn (ptrdiff_t, Lisp_Object, ...);
#define list(...) \
listn (ARRAYELTS (((Lisp_Object []) {__VA_ARGS__})), __VA_ARGS__)
-#define pure_list(...) \
- pure_listn (ARRAYELTS (((Lisp_Object []) {__VA_ARGS__})), __VA_ARGS__)
enum gc_root_type
{
@@ -4618,18 +4559,8 @@ extern Lisp_Object make_uninit_multibyte_string (EMACS_INT, EMACS_INT);
extern Lisp_Object make_string_from_bytes (const char *, ptrdiff_t, ptrdiff_t);
extern Lisp_Object make_specified_string (const char *,
ptrdiff_t, ptrdiff_t, bool);
-extern Lisp_Object make_pure_string (const char *, ptrdiff_t, ptrdiff_t, bool);
-extern Lisp_Object make_pure_c_string (const char *, ptrdiff_t);
extern void pin_string (Lisp_Object string);
-/* Make a string allocated in pure space, use STR as string data. */
-
-INLINE Lisp_Object
-build_pure_c_string (const char *str)
-{
- return make_pure_c_string (str, strlen (str));
-}
-
/* Make a string from the data at STR, treating it as multibyte if the
data warrants. */
@@ -4639,7 +4570,6 @@ build_string (const char *str)
return make_string (str, strlen (str));
}
-extern Lisp_Object pure_cons (Lisp_Object, Lisp_Object);
extern Lisp_Object make_vector (ptrdiff_t, Lisp_Object);
extern struct Lisp_Vector *allocate_nil_vector (ptrdiff_t)
ATTRIBUTE_RETURNS_NONNULL;
@@ -4728,7 +4658,7 @@ void *hash_table_alloc_bytes (ptrdiff_t nbytes) ATTRIBUTE_MALLOC_SIZE ((1));
void hash_table_free_bytes (void *p, ptrdiff_t nbytes);
/* Defined in gmalloc.c. */
-#if !defined DOUG_LEA_MALLOC && !defined HYBRID_MALLOC && !defined SYSTEM_MALLOC
+#if !defined DOUG_LEA_MALLOC && !defined SYSTEM_MALLOC
extern size_t __malloc_extra_blocks;
#endif
#if !HAVE_DECL_ALIGNED_ALLOC
@@ -4931,49 +4861,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 <stdlib.h>
-# 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 <stdlib.h>
-# 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. */
@@ -5614,7 +5501,7 @@ INLINE struct Lisp_Native_Comp_Unit *
allocate_native_comp_unit (void)
{
return ALLOCATE_ZEROED_PSEUDOVECTOR (struct Lisp_Native_Comp_Unit,
- data_impure_vec, PVEC_NATIVE_COMP_UNIT);
+ data_vec, PVEC_NATIVE_COMP_UNIT);
}
#else
INLINE bool
diff --git a/src/lread.c b/src/lread.c
index de1b0ae2d06..6af95873bb8 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1673,7 +1673,7 @@ Return t if the file exists and loads successfully. */)
}
if (! NILP (Vpurify_flag))
- Vpreloaded_file_list = Fcons (Fpurecopy (file), Vpreloaded_file_list);
+ Vpreloaded_file_list = Fcons (file, Vpreloaded_file_list);
if (NILP (nomessage) || force_load_messages)
{
@@ -2490,11 +2490,11 @@ readevalloop (Lisp_Object readcharfun,
if (! HASH_TABLE_P (read_objects_map)
|| XHASH_TABLE (read_objects_map)->count)
read_objects_map
- = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None, false);
+ = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None);
if (! HASH_TABLE_P (read_objects_completed)
|| XHASH_TABLE (read_objects_completed)->count)
read_objects_completed
- = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None, false);
+ = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None);
if (!NILP (Vpurify_flag) && c == '(')
val = read0 (readcharfun, false);
else
@@ -2738,11 +2738,11 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end,
if (! HASH_TABLE_P (read_objects_map)
|| XHASH_TABLE (read_objects_map)->count)
read_objects_map
- = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None, false);
+ = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None);
if (! HASH_TABLE_P (read_objects_completed)
|| XHASH_TABLE (read_objects_completed)->count)
read_objects_completed
- = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None, false);
+ = make_hash_table (&hashtest_eq, DEFAULT_HASH_SIZE, Weak_None);
if (STRINGP (stream)
|| ((CONSP (stream) && STRINGP (XCAR (stream)))))
@@ -4431,10 +4431,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
if (uninterned_symbol)
{
Lisp_Object name
- = (!NILP (Vpurify_flag)
- ? make_pure_string (read_buffer, nchars, nbytes, multibyte)
- : make_specified_string (read_buffer, nchars, nbytes,
- multibyte));
+ = make_specified_string (read_buffer, nchars, nbytes, multibyte);
result = Fmake_symbol (name);
}
else
@@ -4966,10 +4963,7 @@ intern_c_string_1 (const char *str, ptrdiff_t len)
{
Lisp_Object string;
- if (NILP (Vpurify_flag))
- string = make_string (str, len);
- else
- string = make_pure_c_string (str, len);
+ string = make_string (str, len);
tem = intern_driver (string, obarray, tem);
}
@@ -4992,7 +4986,7 @@ static void
define_symbol (Lisp_Object sym, char const *str)
{
ptrdiff_t len = strlen (str);
- Lisp_Object string = make_pure_c_string (str, len);
+ Lisp_Object string = make_string (str, len);
init_symbol (sym, string);
/* Qunbound is uninterned, so that it's not confused with any symbol
@@ -5036,8 +5030,7 @@ it defaults to the value of `obarray'. */)
xfree (longhand);
}
else
- tem = intern_driver (NILP (Vpurify_flag) ? string : Fpurecopy (string),
- obarray, tem);
+ tem = intern_driver (string, obarray, tem);
}
return tem;
}
@@ -5480,7 +5473,7 @@ defsubr (union Aligned_Lisp_Subr *aname)
set_symbol_function (sym, tem);
#ifdef HAVE_NATIVE_COMP
eassert (NILP (Vcomp_abi_hash));
- Vcomp_subr_list = Fpurecopy (Fcons (tem, Vcomp_subr_list));
+ Vcomp_subr_list = Fcons (tem, Vcomp_subr_list);
#endif
}
@@ -5866,19 +5859,19 @@ This list includes suffixes for both compiled and source Emacs Lisp files.
This list should not include the empty string.
`load' and related functions try to append these suffixes, in order,
to the specified file name if a suffix is allowed or required. */);
- Vload_suffixes = list2 (build_pure_c_string (".elc"),
- build_pure_c_string (".el"));
+ Vload_suffixes = list2 (build_string (".elc"),
+ build_string (".el"));
#ifdef HAVE_MODULES
- Vload_suffixes = Fcons (build_pure_c_string (MODULES_SUFFIX), Vload_suffixes);
+ Vload_suffixes = Fcons (build_string (MODULES_SUFFIX), Vload_suffixes);
#ifdef MODULES_SECONDARY_SUFFIX
Vload_suffixes =
- Fcons (build_pure_c_string (MODULES_SECONDARY_SUFFIX), Vload_suffixes);
+ Fcons (build_string (MODULES_SECONDARY_SUFFIX), Vload_suffixes);
#endif
#endif
DEFVAR_LISP ("module-file-suffix", Vmodule_file_suffix,
doc: /* Suffix of loadable module file, or nil if modules are not supported. */);
#ifdef HAVE_MODULES
- Vmodule_file_suffix = build_pure_c_string (MODULES_SUFFIX);
+ Vmodule_file_suffix = build_string (MODULES_SUFFIX);
#else
Vmodule_file_suffix = Qnil;
#endif
@@ -5888,9 +5881,9 @@ to the specified file name if a suffix is allowed or required. */);
#ifndef MSDOS
Vdynamic_library_suffixes
- = Fcons (build_pure_c_string (DYNAMIC_LIB_SECONDARY_SUFFIX), Qnil);
+ = Fcons (build_string (DYNAMIC_LIB_SECONDARY_SUFFIX), Qnil);
Vdynamic_library_suffixes
- = Fcons (build_pure_c_string (DYNAMIC_LIB_SUFFIX),
+ = Fcons (build_string (DYNAMIC_LIB_SUFFIX),
Vdynamic_library_suffixes);
#else
Vdynamic_library_suffixes = Qnil;
@@ -6042,8 +6035,7 @@ from the file, and matches them against this regular expression.
When the regular expression matches, the file is considered to be safe
to load. */);
Vbytecomp_version_regexp
- = build_pure_c_string
- ("^;;;.\\(?:in Emacs version\\|bytecomp version FSF\\)");
+ = build_string ("^;;;.\\(in Emacs version\\|bytecomp version FSF\\)");
DEFSYM (Qlexical_binding, "lexical-binding");
DEFVAR_LISP ("lexical-binding", Vlexical_binding,
@@ -6113,7 +6105,7 @@ through `require'. */);
#if !IEEE_FLOATING_POINT
for (int negative = 0; negative < 2; negative++)
{
- not_a_number[negative] = build_pure_c_string (&"-0.0e+NaN"[!negative]);
+ not_a_number[negative] = build_string (&"-0.0e+NaN"[!negative]);
staticpro (&not_a_number[negative]);
}
#endif
diff --git a/src/pdumper.c b/src/pdumper.c
index 71d82629b56..b2ceea2f8bd 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2469,7 +2469,7 @@ dump_symbol (struct dump_context *ctx,
Lisp_Object object,
dump_off offset)
{
-#if CHECK_STRUCTS && !defined HASH_Lisp_Symbol_61B174C9F4
+#if CHECK_STRUCTS && !defined HASH_Lisp_Symbol_E0ADAF2F24
# error "Lisp_Symbol changed. See CHECK_STRUCTS comment in config.h."
#endif
#if CHECK_STRUCTS && !defined (HASH_symbol_redirect_EA72E4BFF5)
@@ -2506,7 +2506,6 @@ dump_symbol (struct dump_context *ctx,
DUMP_FIELD_COPY (&out, symbol, u.s.trapped_write);
DUMP_FIELD_COPY (&out, symbol, u.s.interned);
DUMP_FIELD_COPY (&out, symbol, u.s.declared_special);
- DUMP_FIELD_COPY (&out, symbol, u.s.pinned);
dump_field_lv (ctx, &out, symbol, &symbol->u.s.name, WEIGHT_STRONG);
switch (symbol->u.s.redirect)
{
@@ -2752,7 +2751,6 @@ dump_hash_table (struct dump_context *ctx, Lisp_Object object)
dump_pseudovector_lisp_fields (ctx, &out->header, &hash->header);
DUMP_FIELD_COPY (out, hash, count);
DUMP_FIELD_COPY (out, hash, weakness);
- DUMP_FIELD_COPY (out, hash, purecopy);
DUMP_FIELD_COPY (out, hash, mutable);
DUMP_FIELD_COPY (out, hash, frozen_test);
if (hash->key_and_value)
@@ -4152,12 +4150,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");
@@ -4168,8 +4160,6 @@ types. */)
calln (intern_c_string ("load--fixup-all-elns"));
#endif
- check_pure_size ();
-
/* Clear out any detritus in memory. */
do
{
@@ -5517,13 +5507,13 @@ dump_do_dump_relocation (const uintptr_t dump_base,
if (!NILP (lambda_data_idx))
{
/* This is an anonymous lambda.
- We must fixup d_reloc_imp so the lambda can be referenced
+ We must fixup d_reloc so the lambda can be referenced
by code. */
Lisp_Object tem;
XSETSUBR (tem, subr);
Lisp_Object *fixup =
- &(comp_u->data_imp_relocs[XFIXNUM (lambda_data_idx)]);
- eassert (EQ (*fixup, Qlambda_fixup));
+ &(comp_u->data_relocs[XFIXNUM (lambda_data_idx)]);
+ eassert (EQ (*fixup, Q__lambda_fixup));
*fixup = tem;
Fputhash (tem, Qt, comp_u->lambda_gc_guard_h);
}
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 2c87ba8e326..73cd6e5695d 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -3881,7 +3881,7 @@ syms_of_pgtkfns (void)
GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
GTK_MICRO_VERSION);
int len = strlen (ver);
- Vgtk_version_string = make_pure_string (ver, len, len, false);
+ Vgtk_version_string = make_specified_string (ver, len, len, false);
g_free (ver);
}
@@ -3895,7 +3895,7 @@ syms_of_pgtkfns (void)
CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
CAIRO_VERSION_MICRO);
int len = strlen (ver);
- Vcairo_version_string = make_pure_string (ver, len, len, false);
+ Vcairo_version_string = make_specified_string (ver, len, len, false);
g_free (ver);
}
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index dd85d622a62..d47b1da7262 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -7419,7 +7419,7 @@ syms_of_pgtkterm (void)
DEFSYM (Qlatin_1, "latin-1");
xg_default_icon_file
- = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
+ = build_string ("icons/hicolor/scalable/apps/emacs.svg");
staticpro (&xg_default_icon_file);
DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
@@ -7482,7 +7482,7 @@ If set to a non-float value, there will be no wait at all. */);
DEFVAR_LISP ("pgtk-keysym-table", Vpgtk_keysym_table,
doc: /* Hash table of character codes indexed by X keysym codes. */);
- Vpgtk_keysym_table = make_hash_table (&hashtest_eql, 900, Weak_None, false);
+ Vpgtk_keysym_table = make_hash_table (&hashtest_eql, 900, Weak_None);
window_being_scrolled = Qnil;
staticpro (&window_being_scrolled);
diff --git a/src/print.c b/src/print.c
index 43698f309b1..c7cba5bface 100644
--- a/src/print.c
+++ b/src/print.c
@@ -2605,9 +2605,6 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
printcharfun, escapeflag);
}
- if (h->purecopy)
- print_c_string (" purecopy t", printcharfun);
-
ptrdiff_t size = h->count;
if (size > 0)
{
diff --git a/src/process.c b/src/process.c
index 275e86f31d0..807f06f990b 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. */
@@ -9018,7 +9007,7 @@ sentinel or a process filter function has an error. */);
const struct socket_options *sopt;
#define ADD_SUBFEATURE(key, val) \
- subfeatures = pure_cons (pure_cons (key, pure_cons (val, Qnil)), subfeatures)
+ subfeatures = Fcons (Fcons (key, Fcons (val, Qnil)), subfeatures)
ADD_SUBFEATURE (QCnowait, Qt);
#ifdef DATAGRAM_SOCKETS
@@ -9040,7 +9029,7 @@ sentinel or a process filter function has an error. */);
ADD_SUBFEATURE (QCserver, Qt);
for (sopt = socket_options; sopt->name; sopt++)
- subfeatures = pure_cons (intern_c_string (sopt->name), subfeatures);
+ subfeatures = Fcons (intern_c_string (sopt->name), subfeatures);
Fprovide (intern_c_string ("make-network-process"), subfeatures);
}
diff --git a/src/profiler.c b/src/profiler.c
index 03e8d007e9f..43409688a93 100644
--- a/src/profiler.c
+++ b/src/profiler.c
@@ -562,7 +562,7 @@ export_log (struct profiler_log *plog)
the log but close enough, and will never confuse two distinct
keys in the log. */
Lisp_Object h = make_hash_table (&hashtest_equal, DEFAULT_HASH_SIZE,
- Weak_None, false);
+ Weak_None);
for (int i = 0; i < log->size; i++)
{
int count = get_log_count (log, i);
diff --git a/src/puresize.h b/src/puresize.h
deleted file mode 100644
index ee173e3595d..00000000000
--- a/src/puresize.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* How much read-only Lisp storage a dumped Emacs needs.
- Copyright (C) 1993, 2001-2025 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-#ifndef EMACS_PURESIZE_H
-#define EMACS_PURESIZE_H
-
-#include "lisp.h"
-
-INLINE_HEADER_BEGIN
-
-/* Define PURESIZE, the number of bytes of pure Lisp code to leave space for.
-
- At one point, this was defined in config.h, meaning that changing
- PURESIZE would make Make recompile all of Emacs. But only a few
- files actually use PURESIZE, so we split it out to its own .h file.
-
- Make sure to include this file after config.h, since that tells us
- whether we are running X windows, which tells us how much pure
- storage to allocate. */
-
-/* First define a measure of the amount of data we have. */
-
-/* A system configuration file may set this to request a certain extra
- amount of storage. This is a lot more update-robust that defining
- BASE_PURESIZE or even PURESIZE directly. */
-#ifndef SYSTEM_PURESIZE_EXTRA
-#define SYSTEM_PURESIZE_EXTRA 0
-#endif
-
-#ifndef SITELOAD_PURESIZE_EXTRA
-#define SITELOAD_PURESIZE_EXTRA 0
-#endif
-
-#ifndef BASE_PURESIZE
-#define BASE_PURESIZE (3100000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA)
-#endif
-
-/* Increase BASE_PURESIZE by a ratio depending on the machine's word size. */
-#ifndef PURESIZE_RATIO
-#if EMACS_INT_MAX >> 31 != 0
-#if PTRDIFF_MAX >> 31 != 0
-#define PURESIZE_RATIO 10 / 6 /* Don't surround with `()'. */
-#else
-#define PURESIZE_RATIO 8 / 6 /* Don't surround with `()'. */
-#endif
-#else
-#define PURESIZE_RATIO 1
-#endif
-#endif
-
-#ifdef ENABLE_CHECKING
-/* ENABLE_CHECKING somehow increases the purespace used, probably because
- it tends to cause some macro arguments to be evaluated twice. This is
- a bug, but it's difficult to track it down. */
-#define PURESIZE_CHECKING_RATIO 12 / 10 /* Don't surround with `()'. */
-#else
-#define PURESIZE_CHECKING_RATIO 1
-#endif
-
-/* This is the actual size in bytes to allocate. */
-#ifndef PURESIZE
-#define PURESIZE (BASE_PURESIZE * PURESIZE_RATIO * PURESIZE_CHECKING_RATIO)
-#endif
-
-extern AVOID pure_write_error (Lisp_Object);
-
-extern EMACS_INT pure[];
-
-/* The puresize_h_* macros are private to this include file. */
-
-/* True if PTR is pure. */
-
-#define puresize_h_PURE_P(ptr) \
- ((uintptr_t) (ptr) - (uintptr_t) pure <= PURESIZE)
-
-INLINE bool
-PURE_P (void *ptr)
-{
- return puresize_h_PURE_P (ptr);
-}
-
-/* Signal an error if OBJ is pure. PTR is OBJ untagged. */
-
-#define puresize_h_CHECK_IMPURE(obj, ptr) \
- (PURE_P (ptr) ? pure_write_error (obj) : (void) 0)
-
-INLINE void
-CHECK_IMPURE (Lisp_Object obj, void *ptr)
-{
- puresize_h_CHECK_IMPURE (obj, ptr);
-}
-
-#if DEFINE_KEY_OPS_AS_MACROS
-# define PURE_P(ptr) puresize_h_PURE_P (ptr)
-# define CHECK_IMPURE(obj, ptr) puresize_h_CHECK_IMPURE (obj, ptr)
-#endif
-
-INLINE_HEADER_END
-
-#endif /* EMACS_PURESIZE_H */
diff --git a/src/ralloc.c b/src/ralloc.c
index 0ef87195b78..3fa32ba9fea 100644
--- a/src/ralloc.c
+++ b/src/ralloc.c
@@ -1162,7 +1162,7 @@ r_alloc_init (void)
r_alloc_initialized = 1;
page_size = PAGE;
-#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
+#if !defined SYSTEM_MALLOC
real_morecore = __morecore;
__morecore = r_alloc_sbrk;
@@ -1181,7 +1181,7 @@ r_alloc_init (void)
mallopt (M_TOP_PAD, 64 * 4096);
unblock_input ();
#else
-#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
+#if !defined SYSTEM_MALLOC
/* Give GNU malloc's morecore some hysteresis so that we move all
the relocatable blocks much less often. The number used to be
64, but alloc.c would override that with 32 in code that was
@@ -1194,7 +1194,7 @@ r_alloc_init (void)
#endif
#endif
-#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
+#if !defined SYSTEM_MALLOC
first_heap->end = (void *) PAGE_ROUNDUP (first_heap->start);
/* The extra call to real_morecore guarantees that the end of the
diff --git a/src/search.c b/src/search.c
index f0672fca151..4a1a4868a82 100644
--- a/src/search.c
+++ b/src/search.c
@@ -3454,19 +3454,19 @@ syms_of_search (void)
DEFSYM (Qinvalid_regexp, "invalid-regexp");
Fput (Qsearch_failed, Qerror_conditions,
- pure_list (Qsearch_failed, Qerror));
+ list (Qsearch_failed, Qerror));
Fput (Qsearch_failed, Qerror_message,
- build_pure_c_string ("Search failed"));
+ build_string ("Search failed"));
Fput (Quser_search_failed, Qerror_conditions,
- pure_list (Quser_search_failed, Quser_error, Qsearch_failed, Qerror));
+ list (Quser_search_failed, Quser_error, Qsearch_failed, Qerror));
Fput (Quser_search_failed, Qerror_message,
- build_pure_c_string ("Search failed"));
+ build_string ("Search failed"));
Fput (Qinvalid_regexp, Qerror_conditions,
- pure_list (Qinvalid_regexp, Qerror));
+ list (Qinvalid_regexp, Qerror));
Fput (Qinvalid_regexp, Qerror_message,
- build_pure_c_string ("Invalid regexp"));
+ build_string ("Invalid regexp"));
re_match_object = Qnil;
staticpro (&re_match_object);
diff --git a/src/sheap.c b/src/sheap.c
deleted file mode 100644
index ff23c702c2b..00000000000
--- a/src/sheap.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* simulate `sbrk' with an array in .bss, for `unexec' support for Cygwin;
- complete rewrite of xemacs Cygwin `unexec' code
-
- Copyright (C) 2004-2025 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-#include <config.h>
-
-#include "sheap.h"
-
-#include <stdio.h>
-#include "lisp.h"
-#include <unistd.h>
-#include <stdlib.h> /* for exit */
-
-static int debug_sheap;
-
-char bss_sbrk_buffer[STATIC_HEAP_SIZE];
-char *max_bss_sbrk_ptr;
-
-void *
-bss_sbrk (ptrdiff_t request_size)
-{
- static char *bss_sbrk_ptr;
-
- if (!bss_sbrk_ptr)
- {
- max_bss_sbrk_ptr = bss_sbrk_ptr = bss_sbrk_buffer;
-#ifdef CYGWIN
- /* Force space for fork to work. */
- sbrk (4096);
-#endif
- }
-
- int used = bss_sbrk_ptr - bss_sbrk_buffer;
-
- if (request_size < -used)
- {
- printf (("attempt to free too much: "
- "avail %d used %d failed request %"pD"d\n"),
- STATIC_HEAP_SIZE, used, request_size);
- exit (-1);
- return 0;
- }
- else if (STATIC_HEAP_SIZE - used < request_size)
- {
- printf ("static heap exhausted: avail %d used %d failed request %"pD"d\n",
- STATIC_HEAP_SIZE, used, request_size);
- exit (-1);
- return 0;
- }
-
- void *ret = bss_sbrk_ptr;
- bss_sbrk_ptr += request_size;
- if (max_bss_sbrk_ptr < bss_sbrk_ptr)
- max_bss_sbrk_ptr = bss_sbrk_ptr;
- if (debug_sheap)
- {
- if (request_size < 0)
- printf ("freed size %"pD"d\n", request_size);
- else
- printf ("allocated %p size %"pD"d\n", ret, request_size);
- }
- return ret;
-}
diff --git a/src/sheap.h b/src/sheap.h
deleted file mode 100644
index 331494e8774..00000000000
--- a/src/sheap.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Static heap allocation for GNU Emacs.
-
-Copyright 2016-2025 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-#include <stddef.h>
-#include "lisp.h"
-
-/* Size of the static heap. Guess a value that is probably too large,
- by up to a factor of four or so. Typically the unused part is not
- paged in and so does not cost much. */
-enum { STATIC_HEAP_SIZE = sizeof (Lisp_Object) << 24 };
-
-extern char bss_sbrk_buffer[STATIC_HEAP_SIZE];
-extern char *max_bss_sbrk_ptr;
-extern void *bss_sbrk (ptrdiff_t);
diff --git a/src/sqlite.c b/src/sqlite.c
index ec3f1b54c96..0de7488d8fd 100644
--- a/src/sqlite.c
+++ b/src/sqlite.c
@@ -899,15 +899,15 @@ syms_of_sqlite (void)
DEFSYM (Qsqlite_error, "sqlite-error");
Fput (Qsqlite_error, Qerror_conditions,
- Fpurecopy (list2 (Qsqlite_error, Qerror)));
+ list2 (Qsqlite_error, Qerror));
Fput (Qsqlite_error, Qerror_message,
- build_pure_c_string ("Database error"));
+ build_string ("Database error"));
DEFSYM (Qsqlite_locked_error, "sqlite-locked-error");
Fput (Qsqlite_locked_error, Qerror_conditions,
- Fpurecopy (list3 (Qsqlite_locked_error, Qsqlite_error, Qerror)));
+ list3 (Qsqlite_locked_error, Qsqlite_error, Qerror));
Fput (Qsqlite_locked_error, Qerror_message,
- build_pure_c_string ("Database locked"));
+ build_string ("Database locked"));
DEFSYM (Qsqlitep, "sqlitep");
DEFSYM (Qfalse, "false");
diff --git a/src/syntax.c b/src/syntax.c
index e25618ee03d..91dbe6a5f83 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -3742,9 +3742,9 @@ syms_of_syntax (void)
DEFSYM (Qscan_error, "scan-error");
Fput (Qscan_error, Qerror_conditions,
- pure_list (Qscan_error, Qerror));
+ list (Qscan_error, Qerror));
Fput (Qscan_error, Qerror_message,
- build_pure_c_string ("Scan error"));
+ build_string ("Scan error"));
DEFVAR_BOOL ("parse-sexp-ignore-comments", parse_sexp_ignore_comments,
doc: /* Non-nil means `forward-sexp', etc., should treat comments as whitespace. */);
diff --git a/src/sysdep.c b/src/sysdep.c
index 3d9c49d9280..a161b4af100 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;
@@ -289,11 +287,7 @@ get_current_dir_name_or_unreachable (void)
#endif
# if HAVE_GET_CURRENT_DIR_NAME && !BROKEN_GET_CURRENT_DIR_NAME
-# ifdef HYBRID_MALLOC
- bool use_libc = will_dump_with_unexec_p ();
-# else
bool use_libc = true;
-# endif
if (use_libc)
{
/* For an unreachable directory, this returns a string that starts
@@ -2036,12 +2030,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/treesit.c b/src/treesit.c
index 2c14f965c2d..62606d99749 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -4481,43 +4481,43 @@ applies to LANGUAGE-A will be redirected to LANGUAGE-B instead. */);
Fmake_variable_buffer_local (Qtreesit_language_remap_alist);
staticpro (&Vtreesit_str_libtree_sitter);
- Vtreesit_str_libtree_sitter = build_pure_c_string ("libtree-sitter-");
+ Vtreesit_str_libtree_sitter = build_string ("libtree-sitter-");
staticpro (&Vtreesit_str_tree_sitter);
- Vtreesit_str_tree_sitter = build_pure_c_string ("tree-sitter-");
+ Vtreesit_str_tree_sitter = build_string ("tree-sitter-");
#ifndef WINDOWSNT
staticpro (&Vtreesit_str_dot_0);
- Vtreesit_str_dot_0 = build_pure_c_string (".0");
+ Vtreesit_str_dot_0 = build_string (".0");
#endif
staticpro (&Vtreesit_str_dot);
- Vtreesit_str_dot = build_pure_c_string (".");
+ Vtreesit_str_dot = build_string (".");
staticpro (&Vtreesit_str_question_mark);
- Vtreesit_str_question_mark = build_pure_c_string ("?");
+ Vtreesit_str_question_mark = build_string ("?");
staticpro (&Vtreesit_str_star);
- Vtreesit_str_star = build_pure_c_string ("*");
+ Vtreesit_str_star = build_string ("*");
staticpro (&Vtreesit_str_plus);
- Vtreesit_str_plus = build_pure_c_string ("+");
+ Vtreesit_str_plus = build_string ("+");
staticpro (&Vtreesit_str_pound_equal);
- Vtreesit_str_pound_equal = build_pure_c_string ("#equal");
+ Vtreesit_str_pound_equal = build_string ("#equal");
staticpro (&Vtreesit_str_pound_match);
- Vtreesit_str_pound_match = build_pure_c_string ("#match");
+ Vtreesit_str_pound_match = build_string ("#match");
staticpro (&Vtreesit_str_pound_pred);
- Vtreesit_str_pound_pred = build_pure_c_string ("#pred");
+ Vtreesit_str_pound_pred = build_string ("#pred");
staticpro (&Vtreesit_str_open_bracket);
- Vtreesit_str_open_bracket = build_pure_c_string ("[");
+ Vtreesit_str_open_bracket = build_string ("[");
staticpro (&Vtreesit_str_close_bracket);
- Vtreesit_str_close_bracket = build_pure_c_string ("]");
+ Vtreesit_str_close_bracket = build_string ("]");
staticpro (&Vtreesit_str_open_paren);
- Vtreesit_str_open_paren = build_pure_c_string ("(");
+ Vtreesit_str_open_paren = build_string ("(");
staticpro (&Vtreesit_str_close_paren);
- Vtreesit_str_close_paren = build_pure_c_string (")");
+ Vtreesit_str_close_paren = build_string (")");
staticpro (&Vtreesit_str_space);
- Vtreesit_str_space = build_pure_c_string (" ");
+ Vtreesit_str_space = build_string (" ");
staticpro (&Vtreesit_str_equal);
- Vtreesit_str_equal = build_pure_c_string ("equal");
+ Vtreesit_str_equal = build_string ("equal");
staticpro (&Vtreesit_str_match);
- Vtreesit_str_match = build_pure_c_string ("match");
+ Vtreesit_str_match = build_string ("match");
staticpro (&Vtreesit_str_pred);
- Vtreesit_str_pred = build_pure_c_string ("pred");
+ Vtreesit_str_pred = build_string ("pred");
defsubr (&Streesit_language_available_p);
defsubr (&Streesit_library_abi_version);
diff --git a/src/unexaix.c b/src/unexaix.c
deleted file mode 100644
index 90c6cb7470c..00000000000
--- a/src/unexaix.c
+++ /dev/null
@@ -1,611 +0,0 @@
-/* Dump an executable file.
- Copyright (C) 1985-1988, 1999, 2001-2025 Free Software Foundation,
- Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-/*
-In other words, you are welcome to use, share and improve this program.
-You are forbidden to forbid anyone else to use, share and improve
-what you give them. Help stamp out software-hoarding! */
-
-
-/* Originally based on the COFF unexec.c by Spencer W. Thomas.
- *
- * Subsequently hacked on by
- * Bill Mann <Bill_Man@praxisint.com>
- * Andrew Vignaux <Andrew.Vignaux@comp.vuw.ac.nz>
- * Mike Sperber <sperber@informatik.uni-tuebingen.de>
- *
- * Synopsis:
- * unexec (const char *new_name, const *old_name);
- *
- * Takes a snapshot of the program and makes an a.out format file in the
- * file named by the string argument new_name.
- * If a_name is non-NULL, the symbol table will be taken from the given file.
- * On some machines, an existing a_name file is required.
- *
- */
-
-#include <config.h>
-#include "unexec.h"
-#include "lisp.h"
-
-#define PERROR(file) report_error (file, new)
-#include <a.out.h>
-/* Define getpagesize () if the system does not.
- Note that this may depend on symbols defined in a.out.h
- */
-#include "getpagesize.h"
-
-#include <sys/types.h>
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-extern char _data[];
-extern char _text[];
-
-#include <filehdr.h>
-#include <aouthdr.h>
-#include <scnhdr.h>
-#include <syms.h>
-
-static struct filehdr f_hdr; /* File header */
-static struct aouthdr f_ohdr; /* Optional file header (a.out) */
-static off_t bias; /* Bias to add for growth */
-static off_t lnnoptr; /* Pointer to line-number info within file */
-
-static off_t text_scnptr;
-static off_t data_scnptr;
-#define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1))
-static off_t load_scnptr;
-static off_t orig_load_scnptr;
-static off_t orig_data_scnptr;
-static int unrelocate_symbols (int, int, const char *, const char *);
-
-#ifndef MAX_SECTIONS
-#define MAX_SECTIONS 10
-#endif
-
-static int adjust_lnnoptrs (int, int, const char *);
-
-static int pagemask;
-
-#include "lisp.h"
-
-static _Noreturn void
-report_error (const char *file, int fd)
-{
- int err = errno;
- if (fd)
- emacs_close (fd);
- report_file_errno ("Cannot unexec", build_string (file), err);
-}
-
-#define ERROR0(msg) report_error_1 (new, msg)
-#define ERROR1(msg,x) report_error_1 (new, msg, x)
-#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y)
-
-static _Noreturn void ATTRIBUTE_FORMAT_PRINTF (2, 3)
-report_error_1 (int fd, const char *msg, ...)
-{
- va_list ap;
- emacs_close (fd);
- va_start (ap, msg);
- verror (msg, ap);
- va_end (ap);
-}
-
-static int make_hdr (int, int, const char *, const char *);
-static void mark_x (const char *);
-static int copy_text_and_data (int);
-static int copy_sym (int, int, const char *, const char *);
-static void write_segment (int, char *, char *);
-
-/* ****************************************************************
- * unexec
- *
- * driving logic.
- */
-void
-unexec (const char *new_name, const char *a_name)
-{
- int new = -1, a_out = -1;
-
- if (a_name && (a_out = emacs_open (a_name, O_RDONLY, 0)) < 0)
- {
- PERROR (a_name);
- }
- if ((new = emacs_open (new_name, O_WRONLY | O_CREAT | O_TRUNC, 0777)) < 0)
- {
- PERROR (new_name);
- }
- if (make_hdr (new, a_out,
- a_name, new_name) < 0
- || copy_text_and_data (new) < 0
- || copy_sym (new, a_out, a_name, new_name) < 0
- || adjust_lnnoptrs (new, a_out, new_name) < 0
- || unrelocate_symbols (new, a_out, a_name, new_name) < 0)
- {
- emacs_close (new);
- return;
- }
-
- emacs_close (new);
- if (a_out >= 0)
- emacs_close (a_out);
-}
-
-/* ****************************************************************
- * make_hdr
- *
- * Make the header in the new a.out from the header in core.
- * Modify the text and data sizes.
- */
-static int
-make_hdr (int new, int a_out,
- const char *a_name, const char *new_name)
-{
- int scns;
- uintptr_t bss_start;
- uintptr_t data_start;
-
- struct scnhdr section[MAX_SECTIONS];
- struct scnhdr * f_thdr; /* Text section header */
- struct scnhdr * f_dhdr; /* Data section header */
- struct scnhdr * f_bhdr; /* Bss section header */
- struct scnhdr * f_lhdr; /* Loader section header */
- struct scnhdr * f_tchdr; /* Typechk section header */
- struct scnhdr * f_dbhdr; /* Debug section header */
- struct scnhdr * f_xhdr; /* Except section header */
-
- load_scnptr = orig_load_scnptr = lnnoptr = 0;
- pagemask = getpagesize () - 1;
-
- /* Adjust text/data boundary. */
- data_start = (uintptr_t) _data;
-
- data_start = data_start & ~pagemask; /* (Down) to page boundary. */
-
- bss_start = (uintptr_t) sbrk (0) + pagemask;
- bss_start &= ~ pagemask;
-
- if (data_start > bss_start) /* Can't have negative data size. */
- {
- ERROR2 (("unexec: data_start (0x%"PRIxPTR
- ") can't be greater than bss_start (0x%"PRIxPTR")"),
- data_start, bss_start);
- }
-
- /* Salvage as much info from the existing file as possible */
- f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL;
- f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL;
- if (a_out >= 0)
- {
- if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
- {
- PERROR (a_name);
- }
- if (f_hdr.f_opthdr > 0)
- {
- if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
- {
- PERROR (a_name);
- }
- }
- if (f_hdr.f_nscns > MAX_SECTIONS)
- {
- ERROR0 ("unexec: too many section headers -- increase MAX_SECTIONS");
- }
- /* Loop through section headers */
- for (scns = 0; scns < f_hdr.f_nscns; scns++) {
- struct scnhdr *s = &section[scns];
- if (read (a_out, s, sizeof (*s)) != sizeof (*s))
- {
- PERROR (a_name);
- }
-
-#define CHECK_SCNHDR(ptr, name, flags) \
- if (strcmp (s->s_name, name) == 0) { \
- if (s->s_flags != flags) { \
- fprintf (stderr, "unexec: %lx flags where %x expected in %s section.\n", \
- (unsigned long)s->s_flags, flags, name); \
- } \
- if (ptr) { \
- fprintf (stderr, "unexec: duplicate section header for section %s.\n", \
- name); \
- } \
- ptr = s; \
- }
- CHECK_SCNHDR (f_thdr, _TEXT, STYP_TEXT);
- CHECK_SCNHDR (f_dhdr, _DATA, STYP_DATA);
- CHECK_SCNHDR (f_bhdr, _BSS, STYP_BSS);
- CHECK_SCNHDR (f_lhdr, _LOADER, STYP_LOADER);
- CHECK_SCNHDR (f_dbhdr, _DEBUG, STYP_DEBUG);
- CHECK_SCNHDR (f_tchdr, _TYPCHK, STYP_TYPCHK);
- CHECK_SCNHDR (f_xhdr, _EXCEPT, STYP_EXCEPT);
- }
-
- if (f_thdr == 0)
- {
- ERROR1 ("unexec: couldn't find \"%s\" section", _TEXT);
- }
- if (f_dhdr == 0)
- {
- ERROR1 ("unexec: couldn't find \"%s\" section", _DATA);
- }
- if (f_bhdr == 0)
- {
- ERROR1 ("unexec: couldn't find \"%s\" section", _BSS);
- }
- }
- else
- {
- ERROR0 ("can't build a COFF file from scratch yet");
- }
- orig_data_scnptr = f_dhdr->s_scnptr;
- orig_load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
-
- /* Now we alter the contents of all the f_*hdr variables
- to correspond to what we want to dump. */
-
- /* Indicate that the reloc information is no longer valid for ld (bind);
- we only update it enough to fake out the exec-time loader. */
- f_hdr.f_flags |= (F_RELFLG | F_EXEC);
-
- f_ohdr.dsize = bss_start - f_ohdr.data_start;
- f_ohdr.bsize = 0;
-
- f_dhdr->s_size = f_ohdr.dsize;
- f_bhdr->s_size = f_ohdr.bsize;
- f_bhdr->s_paddr = f_ohdr.data_start + f_ohdr.dsize;
- f_bhdr->s_vaddr = f_ohdr.data_start + f_ohdr.dsize;
-
- /* fix scnptr's */
- {
- off_t ptr = section[0].s_scnptr;
-
- bias = -1;
- for (scns = 0; scns < f_hdr.f_nscns; scns++)
- {
- struct scnhdr *s = &section[scns];
-
- if (s->s_flags & STYP_PAD) /* .pad sections omitted in AIX 4.1 */
- {
- /*
- * the text_start should probably be o_algntext but that doesn't
- * seem to change
- */
- if (f_ohdr.text_start != 0) /* && scns != 0 */
- {
- s->s_size = 512 - (ptr % 512);
- if (s->s_size == 512)
- s->s_size = 0;
- }
- s->s_scnptr = ptr;
- }
- else if (s->s_flags & STYP_DATA)
- s->s_scnptr = ptr;
- else if (!(s->s_flags & (STYP_TEXT | STYP_BSS)))
- {
- if (bias == -1) /* if first section after bss */
- bias = ptr - s->s_scnptr;
-
- s->s_scnptr += bias;
- ptr = s->s_scnptr;
- }
-
- ptr = ptr + s->s_size;
- }
- }
-
- /* fix other pointers */
- for (scns = 0; scns < f_hdr.f_nscns; scns++)
- {
- struct scnhdr *s = &section[scns];
-
- if (s->s_relptr != 0)
- {
- s->s_relptr += bias;
- }
- if (s->s_lnnoptr != 0)
- {
- if (lnnoptr == 0) lnnoptr = s->s_lnnoptr;
- s->s_lnnoptr += bias;
- }
- }
-
- if (f_hdr.f_symptr > 0L)
- {
- f_hdr.f_symptr += bias;
- }
-
- text_scnptr = f_thdr->s_scnptr;
- data_scnptr = f_dhdr->s_scnptr;
- load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
-
- if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
- {
- PERROR (new_name);
- }
-
- if (f_hdr.f_opthdr > 0)
- {
- if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
- {
- PERROR (new_name);
- }
- }
-
- for (scns = 0; scns < f_hdr.f_nscns; scns++) {
- struct scnhdr *s = &section[scns];
- if (write (new, s, sizeof (*s)) != sizeof (*s))
- {
- PERROR (new_name);
- }
- }
-
- return (0);
-}
-
-/* ****************************************************************
-
- *
- * Copy the text and data segments from memory to the new a.out
- */
-static int
-copy_text_and_data (int new)
-{
- char *end;
- char *ptr;
-
- lseek (new, text_scnptr, SEEK_SET);
- ptr = _text;
- end = ptr + f_ohdr.tsize;
- write_segment (new, ptr, end);
-
- lseek (new, data_scnptr, SEEK_SET);
- ptr = (char *) (ptrdiff_t) f_ohdr.data_start;
- end = ptr + f_ohdr.dsize;
- write_segment (new, ptr, end);
-
- return 0;
-}
-
-#define UnexBlockSz (1<<12) /* read/write block size */
-static void
-write_segment (int new, char *ptr, char *end)
-{
- int i, nwrite, ret;
- char zeros[UnexBlockSz];
-
- for (i = 0; ptr < end;)
- {
- /* distance to next block. */
- nwrite = (((ptrdiff_t) ptr + UnexBlockSz) & -UnexBlockSz) - (ptrdiff_t) ptr;
- /* But not beyond specified end. */
- if (nwrite > end - ptr) nwrite = end - ptr;
- ret = write (new, ptr, nwrite);
- /* If write gets a page fault, it means we reached
- a gap between the old text segment and the old data segment.
- This gap has probably been remapped into part of the text segment.
- So write zeros for it. */
- if (ret == -1 && errno == EFAULT)
- {
- memset (zeros, 0, nwrite);
- write (new, zeros, nwrite);
- }
- else if (nwrite != ret)
- {
- int write_errno = errno;
- char buf[1000];
- void *addr = ptr;
- sprintf (buf,
- "unexec write failure: addr %p, fileno %d, size 0x%x, wrote 0x%x, errno %d",
- addr, new, nwrite, ret, errno);
- errno = write_errno;
- PERROR (buf);
- }
- i += nwrite;
- ptr += nwrite;
- }
-}
-
-/* ****************************************************************
- * copy_sym
- *
- * Copy the relocation information and symbol table from the a.out to the new
- */
-static int
-copy_sym (int new, int a_out, const char *a_name, const char *new_name)
-{
- char page[UnexBlockSz];
- int n;
-
- if (a_out < 0)
- return 0;
-
- if (orig_load_scnptr == 0L)
- return 0;
-
- if (lnnoptr && lnnoptr < orig_load_scnptr) /* if there is line number info */
- lseek (a_out, lnnoptr, SEEK_SET); /* start copying from there */
- else
- lseek (a_out, orig_load_scnptr, SEEK_SET); /* Position a.out to symtab. */
-
- while ((n = read (a_out, page, sizeof page)) > 0)
- {
- if (write (new, page, n) != n)
- {
- PERROR (new_name);
- }
- }
- if (n < 0)
- {
- PERROR (a_name);
- }
- return 0;
-}
-
-static int
-adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name)
-{
- int nsyms;
- int naux;
- int new;
- struct syment symentry;
- union auxent auxentry;
-
- if (!lnnoptr || !f_hdr.f_symptr)
- return 0;
-
- if ((new = emacs_open (new_name, O_RDWR, 0)) < 0)
- {
- PERROR (new_name);
- return -1;
- }
-
- lseek (new, f_hdr.f_symptr, SEEK_SET);
- for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
- {
- read (new, &symentry, SYMESZ);
- if (symentry.n_sclass == C_BINCL || symentry.n_sclass == C_EINCL)
- {
- symentry.n_value += bias;
- lseek (new, -SYMESZ, SEEK_CUR);
- write (new, &symentry, SYMESZ);
- }
-
- for (naux = symentry.n_numaux; naux-- != 0; )
- {
- read (new, &auxentry, AUXESZ);
- nsyms++;
- if (naux != 0 /* skip csect auxentry (last entry) */
- && (symentry.n_sclass == C_EXT || symentry.n_sclass == C_HIDEXT))
- {
- auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
- lseek (new, -AUXESZ, SEEK_CUR);
- write (new, &auxentry, AUXESZ);
- }
- }
- }
- emacs_close (new);
-
- return 0;
-}
-
-static int
-unrelocate_symbols (int new, int a_out,
- const char *a_name, const char *new_name)
-{
- int i;
- LDHDR ldhdr;
- LDREL ldrel;
- off_t t_reloc = (intptr_t) _text - f_ohdr.text_start;
-#ifndef ALIGN_DATA_RELOC
- off_t d_reloc = (intptr_t) _data - f_ohdr.data_start;
-#else
- /* This worked (and was needed) before AIX 4.2.
- I have no idea why. -- Mike */
- off_t d_reloc = (intptr_t) _data - ALIGN (f_ohdr.data_start, 2);
-#endif
- int * p;
-
- if (load_scnptr == 0)
- return 0;
-
- lseek (a_out, orig_load_scnptr, SEEK_SET);
- if (read (a_out, &ldhdr, sizeof (ldhdr)) != sizeof (ldhdr))
- {
- PERROR (new_name);
- }
-
-#define SYMNDX_TEXT 0
-#define SYMNDX_DATA 1
-#define SYMNDX_BSS 2
-
- for (i = 0; i < ldhdr.l_nreloc; i++)
- {
- lseek (a_out,
- orig_load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
- SEEK_SET);
-
- if (read (a_out, &ldrel, LDRELSZ) != LDRELSZ)
- {
- PERROR (a_name);
- }
-
- /* move the BSS loader symbols to the DATA segment */
- if (ldrel.l_symndx == SYMNDX_BSS)
- {
- ldrel.l_symndx = SYMNDX_DATA;
-
- lseek (new,
- load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
- SEEK_SET);
-
- if (write (new, &ldrel, LDRELSZ) != LDRELSZ)
- {
- PERROR (new_name);
- }
- }
-
- if (ldrel.l_rsecnm == f_ohdr.o_sndata)
- {
- int orig_int;
-
- lseek (a_out,
- orig_data_scnptr + (ldrel.l_vaddr - f_ohdr.data_start),
- SEEK_SET);
-
- if (read (a_out, (void *) &orig_int, sizeof (orig_int))
- != sizeof (orig_int))
- {
- PERROR (a_name);
- }
-
- p = (int *) (intptr_t) (ldrel.l_vaddr + d_reloc);
-
- switch (ldrel.l_symndx) {
- case SYMNDX_TEXT:
- orig_int = * p - t_reloc;
- break;
-
- case SYMNDX_DATA:
- case SYMNDX_BSS:
- orig_int = * p - d_reloc;
- break;
- }
-
- if (orig_int != * p)
- {
- lseek (new,
- data_scnptr + (ldrel.l_vaddr - f_ohdr.data_start),
- SEEK_SET);
- if (write (new, (void *) &orig_int, sizeof (orig_int))
- != sizeof (orig_int))
- {
- PERROR (new_name);
- }
- }
- }
- }
- return 0;
-}
diff --git a/src/unexcoff.c b/src/unexcoff.c
deleted file mode 100644
index 10930dff287..00000000000
--- a/src/unexcoff.c
+++ /dev/null
@@ -1,540 +0,0 @@
-/* Copyright (C) 1985-1988, 1992-1994, 2001-2025 Free Software
- * Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-
-/*
- * unexcoff.c - Convert a running program into an a.out or COFF file.
- *
- * ==================================================================
- * Note: This file is currently used only by the MSDOS (a.k.a. DJGPP)
- * build of Emacs. If you are not interested in the MSDOS build, you
- * are looking at the wrong version of unexec!
- * ==================================================================
- *
- * Author: Spencer W. Thomas
- * Computer Science Dept.
- * University of Utah
- * Date: Tue Mar 2 1982
- * Originally under the name unexec.c.
- * Modified heavily since then.
- *
- * Synopsis:
- * unexec (const char *new_name, const char *old_name);
- *
- * Takes a snapshot of the program and makes an a.out format file in the
- * file named by the string argument new_name.
- * If a_name is non-NULL, the symbol table will be taken from the given file.
- * On some machines, an existing a_name file is required.
- *
- * If you make improvements I'd like to get them too.
- * harpo!utah-cs!thomas, thomas@Utah-20
- *
- */
-
-/* Modified to support SysVr3 shared libraries by James Van Artsdalen
- * of Dell Computer Corporation. james@bigtex.cactus.org.
- */
-
-#include <config.h>
-#include "unexec.h"
-#include "lisp.h"
-
-#define PERROR(file) report_error (file, new)
-
-#ifdef HAVE_UNEXEC /* all rest of file! */
-
-#ifdef HAVE_COFF_H
-#include <coff.h>
-#ifdef MSDOS
-#include <fcntl.h> /* for O_RDONLY, O_RDWR */
-#include <crt0.h> /* for _crt0_startup_flags and its bits */
-#include <sys/exceptn.h>
-static int save_djgpp_startup_flags;
-#include <libc/atexit.h>
-static struct __atexit *save_atexit_ptr;
-#define filehdr external_filehdr
-#define scnhdr external_scnhdr
-#define syment external_syment
-#define auxent external_auxent
-#define n_numaux e_numaux
-#define n_type e_type
-struct aouthdr
-{
- unsigned short magic; /* type of file */
- unsigned short vstamp; /* version stamp */
- unsigned long tsize; /* text size in bytes, padded to FW bdry*/
- unsigned long dsize; /* initialized data " " */
- unsigned long bsize; /* uninitialized data " " */
- unsigned long entry; /* entry pt. */
- unsigned long text_start;/* base of text used for this file */
- unsigned long data_start;/* base of data used for this file */
-};
-#endif /* MSDOS */
-#else /* not HAVE_COFF_H */
-#include <a.out.h>
-#endif /* not HAVE_COFF_H */
-
-/* Define getpagesize if the system does not.
- Note that this may depend on symbols defined in a.out.h. */
-#include "getpagesize.h"
-
-#ifndef makedev /* Try to detect types.h already loaded */
-#include <sys/types.h>
-#endif /* makedev */
-#include <errno.h>
-
-#include <sys/file.h>
-
-extern int etext;
-
-static long block_copy_start; /* Old executable start point */
-static struct filehdr f_hdr; /* File header */
-static struct aouthdr f_ohdr; /* Optional file header (a.out) */
-long bias; /* Bias to add for growth */
-long lnnoptr; /* Pointer to line-number info within file */
-#define SYMS_START block_copy_start
-
-static long text_scnptr;
-static long data_scnptr;
-
-static long coff_offset;
-
-static int pagemask;
-
-/* Correct an int which is the bit pattern of a pointer to a byte
- into an int which is the number of a byte.
- This is a no-op on ordinary machines, but not on all. */
-
-#define ADDR_CORRECT(x) ((char *) (x) - (char *) 0)
-
-#include "lisp.h"
-
-static void
-report_error (const char *file, int fd)
-{
- int err = errno;
- if (fd)
- emacs_close (fd);
- report_file_errno ("Cannot unexec", build_string (file), err);
-}
-
-#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
-#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1
-#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
-
-static void
-report_error_1 (int fd, const char *msg, int a1, int a2)
-{
- emacs_close (fd);
- error (msg, a1, a2);
-}
-
-static int make_hdr (int, int, const char *, const char *);
-static int copy_text_and_data (int, int);
-static int copy_sym (int, int, const char *, const char *);
-static void mark_x (const char *);
-
-/* ****************************************************************
- * make_hdr
- *
- * Make the header in the new a.out from the header in core.
- * Modify the text and data sizes.
- */
-static int
-make_hdr (int new, int a_out,
- const char *a_name, const char *new_name)
-{
- auto struct scnhdr f_thdr; /* Text section header */
- auto struct scnhdr f_dhdr; /* Data section header */
- auto struct scnhdr f_bhdr; /* Bss section header */
- auto struct scnhdr scntemp; /* Temporary section header */
- register int scns;
- unsigned int bss_start;
- unsigned int data_start;
-
- pagemask = getpagesize () - 1;
-
- /* Adjust text/data boundary. */
- data_start = (int) DATA_START;
- data_start = ADDR_CORRECT (data_start);
- data_start = data_start & ~pagemask; /* (Down) to page boundary. */
-
- bss_start = ADDR_CORRECT (sbrk (0)) + pagemask;
- bss_start &= ~ pagemask;
-
- if (data_start > bss_start) /* Can't have negative data size. */
- {
- ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)",
- data_start, bss_start);
- }
-
- coff_offset = 0L; /* stays zero, except in DJGPP */
-
- /* Salvage as much info from the existing file as possible */
- if (a_out >= 0)
- {
-#ifdef MSDOS
- /* Support the coff-go32-exe format with a prepended stub, since
- this is what GCC 2.8.0 and later generates by default in DJGPP. */
- unsigned short mz_header[3];
-
- if (read (a_out, &mz_header, sizeof (mz_header)) != sizeof (mz_header))
- {
- PERROR (a_name);
- }
- if (mz_header[0] == 0x5a4d || mz_header[0] == 0x4d5a) /* "MZ" or "ZM" */
- {
- coff_offset = (long)mz_header[2] * 512L;
- if (mz_header[1])
- coff_offset += (long)mz_header[1] - 512L;
- lseek (a_out, coff_offset, 0);
- }
- else
- lseek (a_out, 0L, 0);
-#endif /* MSDOS */
- if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
- {
- PERROR (a_name);
- }
- block_copy_start += sizeof (f_hdr);
- if (f_hdr.f_opthdr > 0)
- {
- if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
- {
- PERROR (a_name);
- }
- block_copy_start += sizeof (f_ohdr);
- }
- /* Loop through section headers, copying them in */
- lseek (a_out, coff_offset + sizeof (f_hdr) + f_hdr.f_opthdr, 0);
- for (scns = f_hdr.f_nscns; scns > 0; scns--) {
- if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
- {
- PERROR (a_name);
- }
- if (scntemp.s_scnptr > 0L)
- {
- if (block_copy_start < scntemp.s_scnptr + scntemp.s_size)
- block_copy_start = scntemp.s_scnptr + scntemp.s_size;
- }
- if (strcmp (scntemp.s_name, ".text") == 0)
- {
- f_thdr = scntemp;
- }
- else if (strcmp (scntemp.s_name, ".data") == 0)
- {
- f_dhdr = scntemp;
- }
- else if (strcmp (scntemp.s_name, ".bss") == 0)
- {
- f_bhdr = scntemp;
- }
- }
- }
- else
- {
- ERROR0 ("can't build a COFF file from scratch yet");
- }
-
- /* Now we alter the contents of all the f_*hdr variables
- to correspond to what we want to dump. */
-
- f_hdr.f_flags |= (F_RELFLG | F_EXEC);
- f_ohdr.dsize = bss_start - f_ohdr.data_start;
- f_ohdr.bsize = 0;
- f_thdr.s_size = f_ohdr.tsize;
- f_thdr.s_scnptr = sizeof (f_hdr) + sizeof (f_ohdr);
- f_thdr.s_scnptr += (f_hdr.f_nscns) * (sizeof (f_thdr));
- lnnoptr = f_thdr.s_lnnoptr;
- text_scnptr = f_thdr.s_scnptr;
- f_dhdr.s_paddr = f_ohdr.data_start;
- f_dhdr.s_vaddr = f_ohdr.data_start;
- f_dhdr.s_size = f_ohdr.dsize;
- f_dhdr.s_scnptr = f_thdr.s_scnptr + f_thdr.s_size;
- data_scnptr = f_dhdr.s_scnptr;
- f_bhdr.s_paddr = f_ohdr.data_start + f_ohdr.dsize;
- f_bhdr.s_vaddr = f_ohdr.data_start + f_ohdr.dsize;
- f_bhdr.s_size = f_ohdr.bsize;
- f_bhdr.s_scnptr = 0L;
- bias = f_dhdr.s_scnptr + f_dhdr.s_size - block_copy_start;
-
- if (f_hdr.f_symptr > 0L)
- {
- f_hdr.f_symptr += bias;
- }
-
- if (f_thdr.s_lnnoptr > 0L)
- {
- f_thdr.s_lnnoptr += bias;
- }
-
- if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
- {
- PERROR (new_name);
- }
-
- if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
- {
- PERROR (new_name);
- }
-
- if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr))
- {
- PERROR (new_name);
- }
-
- if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr))
- {
- PERROR (new_name);
- }
-
- if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr))
- {
- PERROR (new_name);
- }
-
- return (0);
-
-}
-
-void
-write_segment (int new, const char *ptr, const char *end)
-{
- register int i, nwrite, ret;
- /* This is the normal amount to write at once.
- It is the size of block that NFS uses. */
- int writesize = 1 << 13;
- int pagesize = getpagesize ();
- char zeros[1 << 13];
-
- memset (zeros, 0, sizeof (zeros));
-
- for (i = 0; ptr < end;)
- {
- /* Distance to next multiple of writesize. */
- nwrite = (((int) ptr + writesize) & -writesize) - (int) ptr;
- /* But not beyond specified end. */
- if (nwrite > end - ptr) nwrite = end - ptr;
- ret = write (new, ptr, nwrite);
- /* If write gets a page fault, it means we reached
- a gap between the old text segment and the old data segment.
- This gap has probably been remapped into part of the text segment.
- So write zeros for it. */
- if (ret == -1 && errno == EFAULT)
- {
- /* Write only a page of zeros at once,
- so that we don't overshoot the start
- of the valid memory in the old data segment. */
- if (nwrite > pagesize)
- nwrite = pagesize;
- write (new, zeros, nwrite);
- }
- i += nwrite;
- ptr += nwrite;
- }
-}
-/* ****************************************************************
- * copy_text_and_data
- *
- * Copy the text and data segments from memory to the new a.out
- */
-static int
-copy_text_and_data (int new, int a_out)
-{
- register char *end;
- register char *ptr;
-
-#ifdef MSDOS
- /* Dump the original table of exception handlers, not the one
- where our exception hooks are registered. */
- __djgpp_exception_toggle ();
-
- /* Switch off startup flags that might have been set at runtime
- and which might change the way that dumped Emacs works. */
- save_djgpp_startup_flags = _crt0_startup_flags;
- _crt0_startup_flags &= ~(_CRT0_FLAG_NO_LFN | _CRT0_FLAG_NEARPTR);
-
- /* Zero out the 'atexit' chain in the dumped executable, to avoid
- calling the atexit functions twice. (emacs.c:main installs an
- atexit function.) */
- save_atexit_ptr = __atexit_ptr;
- __atexit_ptr = NULL;
-#endif
-
- lseek (new, (long) text_scnptr, 0);
- ptr = (char *) f_ohdr.text_start;
- end = ptr + f_ohdr.tsize;
- write_segment (new, ptr, end);
-
- lseek (new, (long) data_scnptr, 0);
- ptr = (char *) f_ohdr.data_start;
- end = ptr + f_ohdr.dsize;
- write_segment (new, ptr, end);
-
-#ifdef MSDOS
- /* Restore our exception hooks. */
- __djgpp_exception_toggle ();
-
- /* Restore the startup flags. */
- _crt0_startup_flags = save_djgpp_startup_flags;
-
- /* Restore the atexit chain. */
- __atexit_ptr = save_atexit_ptr;
-#endif
-
-
- return 0;
-}
-
-/* ****************************************************************
- * copy_sym
- *
- * Copy the relocation information and symbol table from the a.out to the new
- */
-static int
-copy_sym (int new, int a_out, const char *a_name, const char *new_name)
-{
- char page[1024];
- int n;
-
- if (a_out < 0)
- return 0;
-
- if (SYMS_START == 0L)
- return 0;
-
- if (lnnoptr) /* if there is line number info */
- lseek (a_out, coff_offset + lnnoptr, 0); /* start copying from there */
- else
- lseek (a_out, coff_offset + SYMS_START, 0); /* Position a.out to symtab. */
-
- while ((n = read (a_out, page, sizeof page)) > 0)
- {
- if (write (new, page, n) != n)
- {
- PERROR (new_name);
- }
- }
- if (n < 0)
- {
- PERROR (a_name);
- }
- return 0;
-}
-
-
-/*
- * If the COFF file contains a symbol table and a line number section,
- * then any auxiliary entries that have values for x_lnnoptr must
- * be adjusted by the amount that the line number section has moved
- * in the file (bias computed in make_hdr). The #@$%&* designers of
- * the auxiliary entry structures used the absolute file offsets for
- * the line number entry rather than an offset from the start of the
- * line number section!
- *
- * When I figure out how to scan through the symbol table and pick out
- * the auxiliary entries that need adjustment, this routine will
- * be fixed. As it is now, all such entries are wrong and sdb
- * will complain. Fred Fish, UniSoft Systems Inc.
- */
-
-/* This function is probably very slow. Instead of reopening the new
- file for input and output it should copy from the old to the new
- using the two descriptors already open (WRITEDESC and READDESC).
- Instead of reading one small structure at a time it should use
- a reasonable size buffer. But I don't have time to work on such
- things, so I am installing it as submitted to me. -- RMS. */
-
-int
-adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name)
-{
- register int nsyms;
- register int new;
- struct syment symentry;
- union auxent auxentry;
-
- if (!lnnoptr || !f_hdr.f_symptr)
- return 0;
-
-#ifdef MSDOS
- if ((new = writedesc) < 0)
-#else
- if ((new = emacs_open (new_name, O_RDWR, 0)) < 0)
-#endif
- {
- PERROR (new_name);
- return -1;
- }
-
- lseek (new, f_hdr.f_symptr, 0);
- for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
- {
- read (new, &symentry, SYMESZ);
- if (symentry.n_numaux)
- {
- read (new, &auxentry, AUXESZ);
- nsyms++;
- if (ISFCN (symentry.n_type) || symentry.n_type == 0x2400)
- {
- auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
- lseek (new, -AUXESZ, 1);
- write (new, &auxentry, AUXESZ);
- }
- }
- }
-#ifndef MSDOS
- emacs_close (new);
-#endif
- return 0;
-}
-
-/* ****************************************************************
- * unexec
- *
- * driving logic.
- */
-void
-unexec (const char *new_name, const char *a_name)
-{
- int new = -1, a_out = -1;
-
- if (a_name && (a_out = emacs_open (a_name, O_RDONLY, 0)) < 0)
- {
- PERROR (a_name);
- }
- if ((new = emacs_open (new_name, O_WRONLY | O_CREAT | O_TRUNC, 0777)) < 0)
- {
- PERROR (new_name);
- }
-
- if (make_hdr (new, a_out, a_name, new_name) < 0
- || copy_text_and_data (new, a_out) < 0
- || copy_sym (new, a_out, a_name, new_name) < 0
- || adjust_lnnoptrs (new, a_out, new_name) < 0
- )
- {
- emacs_close (new);
- return;
- }
-
- emacs_close (new);
- if (a_out >= 0)
- emacs_close (a_out);
-}
-
-#endif /* HAVE_UNEXEC */
diff --git a/src/unexcw.c b/src/unexcw.c
deleted file mode 100644
index 33f148e84e9..00000000000
--- a/src/unexcw.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/* unexec() support for Cygwin;
- complete rewrite of xemacs Cygwin unexec() code
-
- Copyright (C) 2004-2025 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-#include <config.h>
-#include "unexec.h"
-#include "lisp.h"
-#include <stdio.h>
-#include <fcntl.h>
-#include <a.out.h>
-#include <unistd.h>
-#include <assert.h>
-
-#define DOTEXE ".exe"
-
-/*
-** header for Windows executable files
-*/
-typedef struct
-{
- FILHDR file_header;
- PEAOUTHDR file_optional_header;
- SCNHDR section_header[32];
-} exe_header_t;
-
-int debug_unexcw = 0;
-
-/*
-** Read the header from the executable into memory so we can more easily access it.
-*/
-static exe_header_t *
-read_exe_header (int fd, exe_header_t * exe_header_buffer)
-{
- int i;
- MAYBE_UNUSED int ret;
-
- assert (fd >= 0);
- assert (exe_header_buffer != 0);
-
- ret = lseek (fd, 0L, SEEK_SET);
- assert (ret != -1);
-
- ret =
- read (fd, &exe_header_buffer->file_header,
- sizeof (exe_header_buffer->file_header));
- assert (ret == sizeof (exe_header_buffer->file_header));
-
- assert (exe_header_buffer->file_header.e_magic == 0x5a4d);
- assert (exe_header_buffer->file_header.nt_signature == 0x4550);
-#ifdef __x86_64__
- assert (exe_header_buffer->file_header.f_magic == 0x8664);
-#else
- assert (exe_header_buffer->file_header.f_magic == 0x014c);
-#endif
- assert (exe_header_buffer->file_header.f_nscns > 0);
- assert (exe_header_buffer->file_header.f_nscns <=
- ARRAYELTS (exe_header_buffer->section_header));
- assert (exe_header_buffer->file_header.f_opthdr > 0);
-
- ret =
- read (fd, &exe_header_buffer->file_optional_header,
- sizeof (exe_header_buffer->file_optional_header));
- assert (ret == sizeof (exe_header_buffer->file_optional_header));
-
-#ifdef __x86_64__
- assert (exe_header_buffer->file_optional_header.magic == 0x020b);
-#else
- assert (exe_header_buffer->file_optional_header.magic == 0x010b);
-#endif
-
- for (i = 0; i < exe_header_buffer->file_header.f_nscns; ++i)
- {
- ret =
- read (fd, &exe_header_buffer->section_header[i],
- sizeof (exe_header_buffer->section_header[i]));
- assert (ret == sizeof (exe_header_buffer->section_header[i]));
- }
-
- return (exe_header_buffer);
-}
-
-/*
-** Fix the dumped emacs executable:
-**
-** - copy .data section data of interest from running executable into
-** output .exe file
-**
-** - convert .bss section into an initialized data section (like
-** .data) and copy .bss section data of interest from running
-** executable into output .exe file
-*/
-static void
-fixup_executable (int fd)
-{
- exe_header_t exe_header_buffer;
- exe_header_t *exe_header;
- int i;
- MAYBE_UNUSED int ret;
- int found_data = 0;
- int found_bss = 0;
-
- exe_header = read_exe_header (fd, &exe_header_buffer);
- assert (exe_header != 0);
-
- assert (exe_header->file_header.f_nscns > 0);
- for (i = 0; i < exe_header->file_header.f_nscns; ++i)
- {
- unsigned long start_address =
- exe_header->section_header[i].s_vaddr +
- exe_header->file_optional_header.ImageBase;
- unsigned long end_address =
- exe_header->section_header[i].s_vaddr +
- exe_header->file_optional_header.ImageBase +
- exe_header->section_header[i].s_paddr;
- if (debug_unexcw)
- printf ("%8s start %#lx end %#lx\n",
- exe_header->section_header[i].s_name,
- start_address, end_address);
- if (my_edata >= (char *) start_address
- && my_edata < (char *) end_address)
- {
- /* data section */
- ret =
- lseek (fd, (long) (exe_header->section_header[i].s_scnptr),
- SEEK_SET);
- assert (ret != -1);
- ret =
- write (fd, (char *) start_address,
- my_edata - (char *) start_address);
- assert (ret == my_edata - (char *) start_address);
- ++found_data;
- if (debug_unexcw)
- printf (" .data, mem start %#lx mem length %td\n",
- start_address, my_edata - (char *) start_address);
- if (debug_unexcw)
- printf (" .data, file start %d file length %d\n",
- (int) exe_header->section_header[i].s_scnptr,
- (int) exe_header->section_header[i].s_paddr);
- }
- else if (my_endbss >= (char *) start_address
- && my_endbss < (char *) end_address)
- {
- /* bss section */
- ++found_bss;
- if (exe_header->section_header[i].s_flags & 0x00000080)
- {
- /* convert uninitialized data section to initialized data section */
- struct stat statbuf;
- ret = fstat (fd, &statbuf);
- assert (ret != -1);
-
- exe_header->section_header[i].s_flags &= ~0x00000080;
- exe_header->section_header[i].s_flags |= 0x00000040;
-
- exe_header->section_header[i].s_scnptr =
- (statbuf.st_size +
- exe_header->file_optional_header.FileAlignment) /
- exe_header->file_optional_header.FileAlignment *
- exe_header->file_optional_header.FileAlignment;
-
- exe_header->section_header[i].s_size =
- (exe_header->section_header[i].s_paddr +
- exe_header->file_optional_header.FileAlignment) /
- exe_header->file_optional_header.FileAlignment *
- exe_header->file_optional_header.FileAlignment;
-
- /* Make sure the generated bootstrap binary isn't
- * sparse. NT doesn't use a file cache for sparse
- * executables, so if we bootstrap Emacs using a sparse
- * bootstrap-emacs.exe, bootstrap takes about twenty
- * times longer than it would otherwise. */
-
- ret = posix_fallocate (fd,
- ( exe_header->section_header[i].s_scnptr +
- exe_header->section_header[i].s_size ),
- 1);
-
- assert (ret != -1);
-
- ret =
- lseek (fd,
- (long) (exe_header->section_header[i].s_scnptr +
- exe_header->section_header[i].s_size - 1),
- SEEK_SET);
- assert (ret != -1);
- ret = write (fd, "", 1);
- assert (ret == 1);
-
- ret =
- lseek (fd,
- (long) ((char *) &exe_header->section_header[i] -
- (char *) exe_header), SEEK_SET);
- assert (ret != -1);
- ret =
- write (fd, &exe_header->section_header[i],
- sizeof (exe_header->section_header[i]));
- assert (ret == sizeof (exe_header->section_header[i]));
- if (debug_unexcw)
- printf (" seek to %ld, write %zu\n",
- (long) ((char *) &exe_header->section_header[i] -
- (char *) exe_header),
- sizeof (exe_header->section_header[i]));
- }
- /* write initialized data section */
- ret =
- lseek (fd, (long) (exe_header->section_header[i].s_scnptr),
- SEEK_SET);
- assert (ret != -1);
- ret =
- write (fd, (char *) start_address,
- my_endbss - (char *) start_address);
- assert (ret == (my_endbss - (char *) start_address));
- if (debug_unexcw)
- printf (" .bss, mem start %#lx mem length %td\n",
- start_address, my_endbss - (char *) start_address);
- if (debug_unexcw)
- printf (" .bss, file start %d file length %d\n",
- (int) exe_header->section_header[i].s_scnptr,
- (int) exe_header->section_header[i].s_paddr);
- }
- }
- assert (found_bss == 1);
- assert (found_data == 1);
-}
-
-/*
-** Windows likes .exe suffixes on executables.
-*/
-static char *
-add_exe_suffix_if_necessary (const char *name, char *modified)
-{
- int i = strlen (name);
- if (i <= (sizeof (DOTEXE) - 1))
- {
- sprintf (modified, "%s%s", name, DOTEXE);
- }
- else if (!strcasecmp (name + i - (sizeof (DOTEXE) - 1), DOTEXE))
- {
- strcpy (modified, name);
- }
- else
- {
- sprintf (modified, "%s%s", name, DOTEXE);
- }
- return (modified);
-}
-
-void
-unexec (const char *outfile, const char *infile)
-{
- char infile_buffer[FILENAME_MAX];
- char outfile_buffer[FILENAME_MAX];
- int fd_in;
- int fd_out;
- int ret;
- MAYBE_UNUSED int ret2;
-
- infile = add_exe_suffix_if_necessary (infile, infile_buffer);
- outfile = add_exe_suffix_if_necessary (outfile, outfile_buffer);
-
- fd_in = emacs_open (infile, O_RDONLY, 0);
- assert (fd_in >= 0);
- fd_out = emacs_open (outfile, O_RDWR | O_TRUNC | O_CREAT, 0755);
- assert (fd_out >= 0);
- for (;;)
- {
- char buffer[4096];
- ret = read (fd_in, buffer, sizeof (buffer));
- if (ret == 0)
- {
- /* eof */
- break;
- }
- assert (ret > 0);
- /* data */
- ret2 = write (fd_out, buffer, ret);
- assert (ret2 == ret);
- }
- ret = emacs_close (fd_in);
- assert (ret == 0);
-
- fixup_executable (fd_out);
-
- ret = emacs_close (fd_out);
- assert (ret == 0);
-}
diff --git a/src/unexec.h b/src/unexec.h
deleted file mode 100644
index cdb2e8016ea..00000000000
--- a/src/unexec.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef EMACS_UNEXEC_H
-#define EMACS_UNEXEC_H
-void unexec (const char *, const char *);
-#endif /* EMACS_UNEXEC_H */
diff --git a/src/unexelf.c b/src/unexelf.c
deleted file mode 100644
index 1cb1476e267..00000000000
--- a/src/unexelf.c
+++ /dev/null
@@ -1,658 +0,0 @@
-/* Copyright (C) 1985-1988, 1990, 1992, 1999-2025 Free Software
- Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-/*
-In other words, you are welcome to use, share and improve this program.
-You are forbidden to forbid anyone else to use, share and improve
-what you give them. Help stamp out software-hoarding! */
-
-
-/*
- * unexec.c - Convert a running program into an a.out file.
- *
- * Author: Spencer W. Thomas
- * Computer Science Dept.
- * University of Utah
- * Date: Tue Mar 2 1982
- * Modified heavily since then.
- *
- * Synopsis:
- * unexec (const char *new_name, const char *old_name);
- *
- * Takes a snapshot of the program and makes an a.out format file in the
- * file named by the string argument new_name.
- * If old_name is non-NULL, the symbol table will be taken from the given file.
- * On some machines, an existing old_name file is required.
- *
- */
-
-/* We do not use mmap because that fails with NFS.
- Instead we read the whole file, modify it, and write it out. */
-
-#include <config.h>
-#include "unexec.h"
-#include "lisp.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <memory.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#ifdef __QNX__
-# include <sys/elf.h>
-#elif !defined __NetBSD__ && !defined __OpenBSD__
-# include <elf.h>
-#endif
-#include <sys/mman.h>
-#if defined (_SYSTYPE_SYSV)
-#include <sys/elf_mips.h>
-#include <sym.h>
-#endif /* _SYSTYPE_SYSV */
-
-#ifndef MAP_ANON
-#ifdef MAP_ANONYMOUS
-#define MAP_ANON MAP_ANONYMOUS
-#else
-#define MAP_ANON 0
-#endif
-#endif
-
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *) -1)
-#endif
-
-#if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
-/* Declare COFF debugging symbol table. This used to be in
- /usr/include/sym.h, but this file is no longer included in Red Hat
- 5.0 and presumably in any other glibc 2.x based distribution. */
-typedef struct {
- short magic;
- short vstamp;
- int ilineMax;
- int idnMax;
- int ipdMax;
- int isymMax;
- int ioptMax;
- int iauxMax;
- int issMax;
- int issExtMax;
- int ifdMax;
- int crfd;
- int iextMax;
- long cbLine;
- long cbLineOffset;
- long cbDnOffset;
- long cbPdOffset;
- long cbSymOffset;
- long cbOptOffset;
- long cbAuxOffset;
- long cbSsOffset;
- long cbSsExtOffset;
- long cbFdOffset;
- long cbRfdOffset;
- long cbExtOffset;
-} HDRR, *pHDRR;
-#define cbHDRR sizeof (HDRR)
-#define hdrNil ((pHDRR)0)
-#endif
-
-#ifdef __NetBSD__
-/*
- * NetBSD does not have normal-looking user-land ELF support.
- */
-# if defined __alpha__ || defined __sparc_v9__ || defined _LP64
-# define ELFSIZE 64
-# else
-# define ELFSIZE 32
-# endif
-# include <sys/exec_elf.h>
-
-# ifndef PT_LOAD
-# define PT_LOAD Elf_pt_load
-# if 0 /* was in pkgsrc patches for 20.7 */
-# define SHT_PROGBITS Elf_sht_progbits
-# endif
-# define SHT_SYMTAB Elf_sht_symtab
-# define SHT_DYNSYM Elf_sht_dynsym
-# define SHT_NULL Elf_sht_null
-# define SHT_NOBITS Elf_sht_nobits
-# define SHT_REL Elf_sht_rel
-# define SHT_RELA Elf_sht_rela
-
-# define SHN_UNDEF Elf_eshn_undefined
-# define SHN_ABS Elf_eshn_absolute
-# define SHN_COMMON Elf_eshn_common
-# endif /* !PT_LOAD */
-
-# ifdef __alpha__
-# include <sys/exec_ecoff.h>
-# define HDRR struct ecoff_symhdr
-# define pHDRR HDRR *
-# endif /* __alpha__ */
-
-#ifdef __mips__ /* was in pkgsrc patches for 20.7 */
-# define SHT_MIPS_DEBUG DT_MIPS_FLAGS
-# define HDRR struct Elf_Shdr
-#endif /* __mips__ */
-#endif /* __NetBSD__ */
-
-#ifdef __OpenBSD__
-# include <sys/exec_elf.h>
-#endif
-
-#if __GNU_LIBRARY__ - 0 >= 6
-# include <link.h> /* get ElfW etc */
-#endif
-
-#ifndef ElfW
-# define ElfBitsW(bits, type) Elf##bits##_##type
-# ifndef ELFSIZE
-# ifdef _LP64
-# define ELFSIZE 64
-# else
-# define ELFSIZE 32
-# endif
-# endif
- /* This macro expands `bits' before invoking ElfBitsW. */
-# define ElfExpandBitsW(bits, type) ElfBitsW (bits, type)
-# define ElfW(type) ElfExpandBitsW (ELFSIZE, type)
-#endif
-
-/* The code often converts ElfW (Half) values like e_shentsize to ptrdiff_t;
- check that this doesn't lose information. */
-#include <intprops.h>
-static_assert ((! TYPE_SIGNED (ElfW (Half))
- || PTRDIFF_MIN <= TYPE_MINIMUM (ElfW (Half)))
- && TYPE_MAXIMUM (ElfW (Half)) <= PTRDIFF_MAX);
-
-#ifdef UNEXELF_DEBUG
-# define DEBUG_LOG(expr) fprintf (stderr, #expr " 0x%"PRIxMAX"\n", \
- (uintmax_t) (expr))
-#endif
-
-/* Get the address of a particular section or program header entry,
- * accounting for the size of the entries.
- */
-
-static void *
-entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
-{
- char *h = section_h;
- return h + idx * entsize;
-}
-
-#define OLD_SECTION_H(n) \
- (*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize))
-#define NEW_SECTION_H(n) \
- (*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize))
-#define OLD_PROGRAM_H(n) \
- (*(ElfW (Phdr) *) entry_address (old_program_h, n, old_file_h->e_phentsize))
-
-typedef unsigned char byte;
-
-/* ****************************************************************
- * unexec
- *
- * driving logic.
- *
- * In ELF, this works by replacing the old bss SHT_NOBITS section with
- * a new, larger, SHT_PROGBITS section.
- *
- */
-void
-unexec (const char *new_name, const char *old_name)
-{
- int new_file, old_file;
- off_t new_file_size;
-
- /* Pointers to the base of the image of the two files. */
- caddr_t old_base, new_base;
-
-#if MAP_ANON == 0
- int mmap_fd;
-#else
-# define mmap_fd -1
-#endif
-
- /* Pointers to the file, program and section headers for the old and
- new files. */
- ElfW (Ehdr) *old_file_h, *new_file_h;
- ElfW (Phdr) *old_program_h, *new_program_h;
- ElfW (Shdr) *old_section_h, *new_section_h;
-
- /* Point to the section name table. */
- char *old_section_names, *new_section_names;
-
- ElfW (Phdr) *old_bss_seg, *new_bss_seg;
- ElfW (Addr) old_bss_addr, new_bss_addr;
- ElfW (Word) old_bss_size, bss_size_growth, new_data2_size;
- ElfW (Off) old_bss_offset, new_data2_offset;
-
- ptrdiff_t n;
- ptrdiff_t old_bss_index;
- struct stat stat_buf;
- off_t old_file_size;
-
- /* Open the old file, allocate a buffer of the right size, and read
- in the file contents. */
-
- old_file = emacs_open (old_name, O_RDONLY, 0);
-
- if (old_file < 0)
- fatal ("Can't open %s for reading: %s", old_name, strerror (errno));
-
- if (fstat (old_file, &stat_buf) != 0)
- fatal ("Can't fstat (%s): %s", old_name, strerror (errno));
-
-#if MAP_ANON == 0
- mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0);
- if (mmap_fd < 0)
- fatal ("Can't open /dev/zero for reading: %s", strerror (errno));
-#endif
-
- /* We cannot use malloc here because that may use sbrk. If it does,
- we'd dump our temporary buffers with Emacs, and we'd have to be
- extra careful to use the correct value of sbrk(0) after
- allocating all buffers in the code below, which we aren't. */
- old_file_size = stat_buf.st_size;
- if (! (0 <= old_file_size && old_file_size <= SIZE_MAX))
- fatal ("File size out of range");
- old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
- if (old_base == MAP_FAILED)
- fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
-
- if (read (old_file, old_base, old_file_size) != old_file_size)
- fatal ("Didn't read all of %s: %s", old_name, strerror (errno));
-
- /* Get pointers to headers & section names */
-
- old_file_h = (ElfW (Ehdr) *) old_base;
- old_program_h = (ElfW (Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
- old_section_h = (ElfW (Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
- old_section_names = (char *) old_base
- + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
-
- /* Find the PT_LOAD header covering the highest address. This
- segment will be where bss sections are located, past p_filesz. */
- old_bss_seg = 0;
- for (n = old_file_h->e_phnum; --n >= 0; )
- {
- ElfW (Phdr) *seg = &OLD_PROGRAM_H (n);
- if (seg->p_type == PT_LOAD
- && (old_bss_seg == 0
- || seg->p_vaddr > old_bss_seg->p_vaddr))
- old_bss_seg = seg;
- }
- eassume (old_bss_seg);
- if (!old_bss_seg)
- emacs_abort ();
-
- /* Note that old_bss_addr may be lower than the first bss section
- address, since the section may need aligning. */
- old_bss_addr = old_bss_seg->p_vaddr + old_bss_seg->p_filesz;
- old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz;
- old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz;
-
- /* Find the last bss style section in the bss segment range. */
- old_bss_index = -1;
- for (n = old_file_h->e_shnum; --n > 0; )
- {
- ElfW (Shdr) *shdr = &OLD_SECTION_H (n);
- if (shdr->sh_type == SHT_NOBITS
- && shdr->sh_addr >= old_bss_addr
- && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size
- && (old_bss_index == -1
- || OLD_SECTION_H (old_bss_index).sh_addr < shdr->sh_addr))
- old_bss_index = n;
- }
-
- if (old_bss_index == -1)
- fatal ("no bss section found");
-
- void *no_break = (void *) (intptr_t) -1;
- void *new_break = no_break;
-#ifdef HAVE_SBRK
- new_break = sbrk (0);
-#endif
- if (new_break == no_break)
- new_break = (byte *) old_bss_addr + old_bss_size;
- new_bss_addr = (ElfW (Addr)) new_break;
- bss_size_growth = new_bss_addr - old_bss_addr;
- new_data2_size = bss_size_growth;
- new_data2_size += alignof (ElfW (Shdr)) - 1;
- new_data2_size -= new_data2_size % alignof (ElfW (Shdr));
-
- new_data2_offset = old_bss_offset;
-
-#ifdef UNEXELF_DEBUG
- fprintf (stderr, "old_bss_index %td\n", old_bss_index);
- DEBUG_LOG (old_bss_addr);
- DEBUG_LOG (old_bss_size);
- DEBUG_LOG (old_bss_offset);
- DEBUG_LOG (new_bss_addr);
- DEBUG_LOG (new_data2_size);
- DEBUG_LOG (new_data2_offset);
-#endif
-
- if (new_bss_addr < old_bss_addr + old_bss_size)
- fatal (".bss shrank when undumping");
-
- /* Set the output file to the right size. Allocate a buffer to hold
- the image of the new file. Set pointers to various interesting
- objects. */
-
- new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0777);
- if (new_file < 0)
- fatal ("Can't creat (%s): %s", new_name, strerror (errno));
-
- new_file_size = old_file_size + new_data2_size;
-
- if (ftruncate (new_file, new_file_size))
- fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
-
- new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
- if (new_base == MAP_FAILED)
- fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
-
- /* Make our new file, program and section headers as copies of the
- originals. */
-
- new_file_h = (ElfW (Ehdr) *) new_base;
- memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
-
- /* Fix up file header. Section header is further away now. */
-
- if (new_file_h->e_shoff >= old_bss_offset)
- new_file_h->e_shoff += new_data2_size;
-
- new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff);
- new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff);
-
- memcpy (new_program_h, old_program_h,
- old_file_h->e_phnum * old_file_h->e_phentsize);
- memcpy (new_section_h, old_section_h,
- old_file_h->e_shnum * old_file_h->e_shentsize);
-
-#ifdef UNEXELF_DEBUG
- DEBUG_LOG (old_file_h->e_shoff);
- fprintf (stderr, "Old section count %td\n", (ptrdiff_t) old_file_h->e_shnum);
- DEBUG_LOG (new_file_h->e_shoff);
- fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum);
-#endif
-
- /* Fix up program header. Extend the writable data segment so
- that the bss area is covered too. */
-
- new_bss_seg = new_program_h + (old_bss_seg - old_program_h);
- new_bss_seg->p_filesz = new_bss_addr - new_bss_seg->p_vaddr;
- new_bss_seg->p_memsz = new_bss_seg->p_filesz;
-
- /* Copy over what we have in memory now for the bss area. */
- memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr,
- bss_size_growth);
-
- /* Walk through all section headers, copying data and updating. */
- for (n = 1; n < old_file_h->e_shnum; n++)
- {
- caddr_t src;
- ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
- ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
-
- if (new_shdr->sh_type == SHT_NOBITS
- && new_shdr->sh_addr >= old_bss_addr
- && (new_shdr->sh_addr + new_shdr->sh_size
- <= old_bss_addr + old_bss_size))
- {
- /* This section now has file backing. */
- new_shdr->sh_type = SHT_PROGBITS;
-
- /* SHT_NOBITS sections do not need a valid sh_offset, so it
- might be incorrect. Write the correct value. */
- new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
- + new_bss_seg->p_offset);
-
- /* If this is was a SHT_NOBITS .plt section, then it is
- probably a PowerPC PLT. If it is PowerPC64 ELFv1 then
- glibc ld.so doesn't initialize the toc pointer word. A
- non-zero toc pointer word can defeat Power7 thread safety
- during lazy update of a PLT entry. This only matters if
- emacs becomes multi-threaded. */
- if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0)
- memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size);
-
- /* Extend the size of the last bss section to cover dumped
- data. */
- if (n == old_bss_index)
- new_shdr->sh_size = new_bss_addr - new_shdr->sh_addr;
-
- /* We have already copied this section from the current
- process. */
- continue;
- }
-
- /* Any section that was originally placed after the .bss
- section should now be offset by NEW_DATA2_SIZE. */
- if (new_shdr->sh_offset >= old_bss_offset)
- new_shdr->sh_offset += new_data2_size;
-
- /* Now, start to copy the content of sections. */
- if (new_shdr->sh_type == SHT_NULL
- || new_shdr->sh_type == SHT_NOBITS)
- continue;
-
- /* Some sections are copied from the current process instead of
- the old file. */
- if (!strcmp (old_section_names + new_shdr->sh_name, ".data")
- || !strcmp (old_section_names + new_shdr->sh_name, ".sdata")
- || !strcmp (old_section_names + new_shdr->sh_name, ".lit4")
- || !strcmp (old_section_names + new_shdr->sh_name, ".lit8")
- || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1")
- || !strcmp (old_section_names + new_shdr->sh_name, ".data1"))
- src = (caddr_t) old_shdr->sh_addr;
- else
- src = old_base + old_shdr->sh_offset;
-
- memcpy (new_shdr->sh_offset + new_base, src, new_shdr->sh_size);
-
-#if (defined __alpha__ && !defined __OpenBSD__) || defined _SYSTYPE_SYSV
- /* Update Alpha and MIPS COFF debug symbol table. */
- if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
- && new_shdr->sh_offset - old_shdr->sh_offset != 0
-#if defined _SYSTYPE_SYSV
- && new_shdr->sh_type == SHT_MIPS_DEBUG
-#endif
- )
- {
- ptrdiff_t diff = new_shdr->sh_offset - old_shdr->sh_offset;
- HDRR *phdr = (HDRR *) (new_shdr->sh_offset + new_base);
-
- phdr->cbLineOffset += diff;
- phdr->cbDnOffset += diff;
- phdr->cbPdOffset += diff;
- phdr->cbSymOffset += diff;
- phdr->cbOptOffset += diff;
- phdr->cbAuxOffset += diff;
- phdr->cbSsOffset += diff;
- phdr->cbSsExtOffset += diff;
- phdr->cbFdOffset += diff;
- phdr->cbRfdOffset += diff;
- phdr->cbExtOffset += diff;
- }
-#endif /* __alpha__ || _SYSTYPE_SYSV */
- }
-
- /* Update the symbol values of _edata and _end. */
- for (n = new_file_h->e_shnum; 0 < --n; )
- {
- byte *symnames;
- ElfW (Sym) *symp, *symendp;
- ElfW (Shdr) *sym_shdr = &NEW_SECTION_H (n);
-
- if (sym_shdr->sh_type != SHT_DYNSYM
- && sym_shdr->sh_type != SHT_SYMTAB)
- continue;
-
- symnames = ((byte *) new_base
- + NEW_SECTION_H (sym_shdr->sh_link).sh_offset);
- symp = (ElfW (Sym) *) (sym_shdr->sh_offset + new_base);
- symendp = (ElfW (Sym) *) ((byte *) symp + sym_shdr->sh_size);
-
- for (; symp < symendp; symp ++)
- {
- if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
- || strcmp ((char *) (symnames + symp->st_name), "end") == 0
- || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0
- || strcmp ((char *) (symnames + symp->st_name), "edata") == 0)
- memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
-
- /* Strictly speaking, #ifdef below is not necessary. But we
- keep it to indicate that this kind of change may also be
- necessary for other unexecs to support GNUstep. */
-#ifdef NS_IMPL_GNUSTEP
- /* ObjC runtime modifies the values of some data structures
- such as classes and selectors in the .data section after
- loading. As the dump process copies the .data section
- from the current process, that causes problems when the
- modified classes are reinitialized in the dumped
- executable. We copy such data from the old file, not
- from the current process. */
- if (strncmp ((char *) (symnames + symp->st_name),
- "_OBJC_", sizeof ("_OBJC_") - 1) == 0)
- {
- ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx);
- if (new_shdr->sh_type != SHT_NOBITS)
- {
- ElfW (Shdr) *old_shdr = &OLD_SECTION_H (symp->st_shndx);
- ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
- ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
-
- if (old_shdr->sh_type == SHT_NOBITS)
- memset (new_base + newoff, 0, symp->st_size);
- else
- {
- ptrdiff_t oldoff = reladdr + old_shdr->sh_offset;
- memcpy (new_base + newoff, old_base + oldoff,
- symp->st_size);
- }
- }
- }
-#endif
- }
- }
-
- /* Modify the names of sections we changed from SHT_NOBITS to
- SHT_PROGBITS. This is really just cosmetic, but some tools that
- (wrongly) operate on section names rather than types might be
- confused by a SHT_PROGBITS .bss section. */
- new_section_names = ((char *) new_base
- + NEW_SECTION_H (new_file_h->e_shstrndx).sh_offset);
- for (n = new_file_h->e_shnum; 0 < --n; )
- {
- ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
- ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
-
- /* Replace the leading '.' with ','. When .shstrtab is string
- merged this will rename both .bss and .rela.bss to ,bss and
- .rela,bss. */
- if (old_shdr->sh_type == SHT_NOBITS
- && new_shdr->sh_type == SHT_PROGBITS)
- *(new_section_names + new_shdr->sh_name) = ',';
- }
-
- /* This loop seeks out relocation sections for the data section, so
- that it can undo relocations performed by the runtime loader.
-
- The following approach does not work on x86 platforms that use
- the GNU Gold linker, which can generate .rel.dyn relocation
- sections containing R_386_32 entries that the following code does
- not grok. Emacs works around this problem by avoiding C
- constructs that generate such entries, which is horrible hack.
-
- FIXME: Presumably more problems like this will crop up as linkers
- get fancier. We really need to stop assuming that Emacs can grok
- arbitrary linker output. See Bug#27248. */
- for (n = new_file_h->e_shnum; 0 < --n; )
- {
- ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n);
- ElfW (Shdr) *shdr;
-
- switch (rel_shdr->sh_type)
- {
- default:
- break;
- case SHT_REL:
- case SHT_RELA:
- /* This code handles two different size structs, but there should
- be no harm in that provided that r_offset is always the first
- member. */
- shdr = &NEW_SECTION_H (rel_shdr->sh_info);
- if (!strcmp (old_section_names + shdr->sh_name, ".data")
- || !strcmp (old_section_names + shdr->sh_name, ".sdata")
- || !strcmp (old_section_names + shdr->sh_name, ".lit4")
- || !strcmp (old_section_names + shdr->sh_name, ".lit8")
- || !strcmp (old_section_names + shdr->sh_name, ".sdata1")
- || !strcmp (old_section_names + shdr->sh_name, ".data1"))
- {
- ElfW (Addr) offset = shdr->sh_addr - shdr->sh_offset;
- caddr_t reloc = old_base + rel_shdr->sh_offset, end;
- for (end = reloc + rel_shdr->sh_size;
- reloc < end;
- reloc += rel_shdr->sh_entsize)
- {
- ElfW (Addr) addr = ((ElfW (Rel) *) reloc)->r_offset - offset;
- /* Ignore R_*_NONE relocs. */
- if (((ElfW (Rel) *) reloc)->r_offset == 0)
- continue;
- /* Assume reloc applies to a word.
- ??? This is not always true, eg. TLS module/index
- pair in .got which occupies two words. */
- memcpy (new_base + addr, old_base + addr,
- sizeof (ElfW (Addr)));
- }
- }
- break;
- }
- }
-
- /* Write out new_file, and free the buffers. */
-
- if (write (new_file, new_base, new_file_size) != new_file_size)
- fatal ("Didn't write %lu bytes to %s: %s",
- (unsigned long) new_file_size, new_name, strerror (errno));
- munmap (old_base, old_file_size);
- munmap (new_base, new_file_size);
-
- /* Close the files and make the new file executable. */
-
-#if MAP_ANON == 0
- emacs_close (mmap_fd);
-#endif
-
- if (emacs_close (old_file) != 0)
- fatal ("Can't close (%s): %s", old_name, strerror (errno));
-
- if (emacs_close (new_file) != 0)
- fatal ("Can't close (%s): %s", new_name, strerror (errno));
-}
diff --git a/src/unexhp9k800.c b/src/unexhp9k800.c
deleted file mode 100644
index d2943eb18c9..00000000000
--- a/src/unexhp9k800.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/* Unexec for HP 9000 Series 800 machines.
-
- This file is in the public domain.
-
- Author: John V. Morris
-
- This file was written by John V. Morris at Hewlett Packard.
- Both the author and Hewlett Packard Co. have disclaimed the
- copyright on this file, and it is therefore in the public domain.
- (Search for "hp9k800" in copyright.list.)
-*/
-
-/*
- Bob Desinger <hpsemc!bd@hplabs.hp.com>
-
- Note that the GNU project considers support for HP operation a
- peripheral activity which should not be allowed to divert effort
- from development of the GNU system. Changes in this code will be
- installed when users send them in, but aside from that we don't
- plan to think about it, or about whether other Emacs maintenance
- might break it.
-
-
- Unexec creates a copy of the old a.out file, and replaces the old data
- area with the current data area. When the new file is executed, the
- process will see the same data structures and data values that the
- original process had when unexec was called.
-
- Unlike other versions of unexec, this one copies symbol table and
- debug information to the new a.out file. Thus, the new a.out file
- may be debugged with symbolic debuggers.
-
- If you fix any bugs in this, I'd like to incorporate your fixes.
- Send them to uunet!hpda!hpsemc!jmorris or jmorris%hpsemc@hplabs.HP.COM.
-
- CAVEATS:
- This routine saves the current value of all static and external
- variables. This means that any data structure that needs to be
- initialized must be explicitly reset. Variables will not have their
- expected default values.
-
- Unfortunately, the HP-UX signal handler has internal initialization
- flags which are not explicitly reset. Thus, for signals to work in
- conjunction with this routine, the following code must executed when
- the new process starts up.
-
- void _sigreturn ();
- ...
- sigsetreturn (_sigreturn);
-*/
-
-#include <config.h>
-#include "unexec.h"
-#include "lisp.h"
-#include "sysstdio.h"
-
-#include <fcntl.h>
-#include <errno.h>
-#include <a.out.h>
-#include <dl.h>
-
-/* brk value to restore, stored as a global.
- This is really used only if we used shared libraries. */
-static long brk_on_dump = 0;
-
-/* Called from main, if we use shared libraries. */
-int
-run_time_remap (char *ignored)
-{
- brk ((char *) brk_on_dump);
-}
-
-#undef roundup
-#define roundup(x,n) (((x) + ((n) - 1)) & ~((n) - 1)) /* n is power of 2 */
-
-/* Report a fatal error and exit. */
-static _Noreturn void
-unexec_error (char const *msg)
-{
- perror (msg);
- exit (1);
-}
-
-/* Do an lseek and check the result. */
-static void
-check_lseek (int fd, off_t offset, int whence)
-{
- if (lseek (fd, offset, whence) < 0)
- unexec_error ("Cannot lseek");
-}
-
-/* Save current data space in the file, update header. */
-
-static void
-save_data_space (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr,
- int size)
-{
- /* Write the entire data space out to the file */
- if (write (file, auxhdr->exec_dmem, size) != size)
- unexec_error ("Can't save new data space");
-
- /* Update the header to reflect the new data size */
- auxhdr->exec_dsize = size;
- auxhdr->exec_bsize = 0;
-}
-
-/* Update the values of file pointers when something is inserted. */
-
-static void
-update_file_ptrs (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr,
- unsigned int location, int offset)
-{
- struct subspace_dictionary_record subspace;
- int i;
-
- /* Increase the overall size of the module */
- hdr->som_length += offset;
-
- /* Update the various file pointers in the header */
-#define update(ptr) if (ptr > location) ptr = ptr + offset
- update (hdr->aux_header_location);
- update (hdr->space_strings_location);
- update (hdr->init_array_location);
- update (hdr->compiler_location);
- update (hdr->symbol_location);
- update (hdr->fixup_request_location);
- update (hdr->symbol_strings_location);
- update (hdr->unloadable_sp_location);
- update (auxhdr->exec_tfile);
- update (auxhdr->exec_dfile);
-
- /* Do for each subspace dictionary entry */
- check_lseek (file, hdr->subspace_location, 0);
- for (i = 0; i < hdr->subspace_total; i++)
- {
- ptrdiff_t subspace_size = sizeof subspace;
- if (read (file, &subspace, subspace_size) != subspace_size)
- unexec_error ("Can't read subspace record");
-
- /* If subspace has a file location, update it */
- if (subspace.initialization_length > 0
- && subspace.file_loc_init_value > location)
- {
- subspace.file_loc_init_value += offset;
- check_lseek (file, -subspace_size, 1);
- if (write (file, &subspace, subspace_size) != subspace_size)
- unexec_error ("Can't update subspace record");
- }
- }
-
- /* Do for each initialization pointer record */
- /* (I don't think it applies to executable files, only relocatables) */
-#undef update
-}
-
-/* Read in the header records from an a.out file. */
-
-static void
-read_header (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr)
-{
-
- /* Read the header in */
- check_lseek (file, 0, 0);
- if (read (file, hdr, sizeof (*hdr)) != sizeof (*hdr))
- unexec_error ("Couldn't read header from a.out file");
-
- if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC
- && hdr->a_magic != DEMAND_MAGIC)
- {
- fputs ("a.out file doesn't have valid magic number\n", stderr);
- exit (1);
- }
-
- check_lseek (file, hdr->aux_header_location, 0);
- if (read (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr))
- unexec_error ("Couldn't read auxiliary header from a.out file");
-}
-
-/* Write out the header records into an a.out file. */
-
-static void
-write_header (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr)
-{
- /* Update the checksum */
- hdr->checksum = calculate_checksum (hdr);
-
- /* Write the header back into the a.out file */
- check_lseek (file, 0, 0);
- if (write (file, hdr, sizeof (*hdr)) != sizeof (*hdr))
- unexec_error ("Couldn't write header to a.out file");
- check_lseek (file, hdr->aux_header_location, 0);
- if (write (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr))
- unexec_error ("Couldn't write auxiliary header to a.out file");
-}
-
-/* Calculate the checksum of a SOM header record. */
-
-static int
-calculate_checksum (struct header *hdr)
-{
- int checksum, i, *ptr;
-
- checksum = 0; ptr = (int *) hdr;
-
- for (i = 0; i < sizeof (*hdr) / sizeof (int) - 1; i++)
- checksum ^= ptr[i];
-
- return (checksum);
-}
-
-/* Copy size bytes from the old file to the new one. */
-
-static void
-copy_file (int old, int new, int size)
-{
- int len;
- int buffer[8192]; /* word aligned will be faster */
-
- for (; size > 0; size -= len)
- {
- len = min (size, sizeof (buffer));
- if (read (old, buffer, len) != len)
- unexec_error ("Read failure on a.out file");
- if (write (new, buffer, len) != len)
- unexec_error ("Write failure in a.out file");
- }
-}
-
-/* Copy the rest of the file, up to EOF. */
-
-static void
-copy_rest (int old, int new)
-{
- int buffer[4096];
- int len;
-
- /* Copy bytes until end of file or error */
- while ((len = read (old, buffer, sizeof (buffer))) > 0)
- if (write (new, buffer, len) != len) break;
-
- if (len != 0)
- unexec_error ("Unable to copy the rest of the file");
-}
-
-#ifdef DEBUG
-static void
-display_header (struct header *hdr, struct som_exec_auxhdr *auxhdr)
-{
- /* Display the header information (debug) */
- printf ("\n\nFILE HEADER\n");
- printf ("magic number %d \n", hdr->a_magic);
- printf ("text loc %.8x size %d \n", auxhdr->exec_tmem, auxhdr->exec_tsize);
- printf ("data loc %.8x size %d \n", auxhdr->exec_dmem, auxhdr->exec_dsize);
- printf ("entry %x \n", auxhdr->exec_entry);
- printf ("Bss segment size %u\n", auxhdr->exec_bsize);
- printf ("\n");
- printf ("data file loc %d size %d\n",
- auxhdr->exec_dfile, auxhdr->exec_dsize);
- printf ("som_length %d\n", hdr->som_length);
- printf ("unloadable sploc %d size %d\n",
- hdr->unloadable_sp_location, hdr->unloadable_sp_size);
-}
-#endif /* DEBUG */
-
-
-/* Create a new a.out file, same as old but with current data space */
-void
-unexec (const char *new_name, /* name of the new a.out file to be created */
- const char *old_name) /* name of the old a.out file */
-{
- int old, new;
- int old_size, new_size;
- struct header hdr;
- struct som_exec_auxhdr auxhdr;
- long i;
-
- /* For the greatest flexibility, should create a temporary file in
- the same directory as the new file. When everything is complete,
- rename the temp file to the new name.
- This way, a program could update its own a.out file even while
- it is still executing. If problems occur, everything is still
- intact. NOT implemented. */
-
- /* Open the input and output a.out files. */
- old = emacs_open (old_name, O_RDONLY, 0);
- if (old < 0)
- unexec_error (old_name);
- new = emacs_open (new_name, O_CREAT | O_RDWR | O_TRUNC, 0777);
- if (new < 0)
- unexec_error (new_name);
-
- /* Read the old headers. */
- read_header (old, &hdr, &auxhdr);
-
- brk_on_dump = (long) sbrk (0);
-
- /* Decide how large the new and old data areas are. */
- old_size = auxhdr.exec_dsize;
- /* I suspect these two statements are separate
- to avoid a compiler bug in hpux version 8. */
- i = (long) sbrk (0);
- new_size = i - auxhdr.exec_dmem;
-
- /* Copy the old file to the new, up to the data space. */
- check_lseek (old, 0, 0);
- copy_file (old, new, auxhdr.exec_dfile);
-
- /* Skip the old data segment and write a new one. */
- check_lseek (old, old_size, 1);
- save_data_space (new, &hdr, &auxhdr, new_size);
-
- /* Copy the rest of the file. */
- copy_rest (old, new);
-
- /* Update file pointers since we probably changed size of data area. */
- update_file_ptrs (new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size);
-
- /* Save the modified header. */
- write_header (new, &hdr, &auxhdr);
-
- /* Close the binary file. */
- emacs_close (old);
- emacs_close (new);
-}
diff --git a/src/unexmacosx.c b/src/unexmacosx.c
deleted file mode 100644
index 10524224711..00000000000
--- a/src/unexmacosx.c
+++ /dev/null
@@ -1,1401 +0,0 @@
-/* Dump Emacs in Mach-O format for use on macOS.
- Copyright (C) 2001-2025 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Contributed by Andrew Choi (akochoi@mac.com). */
-
-/* Documentation note.
-
- Consult the following documents/files for a description of the
- Mach-O format: the file loader.h, man pages for Mach-O and ld, old
- NEXTSTEP documents of the Mach-O format. The tool otool dumps the
- mach header (-h option) and the load commands (-l option) in a
- Mach-O file. The tool nm on macOS displays the symbol table in
- a Mach-O file. For examples of unexec for the Mach-O format, see
- the file unexnext.c in the GNU Emacs distribution, the file
- unexdyld.c in the Darwin port of GNU Emacs 20.7, and unexdyld.c in
- the Darwin port of XEmacs 21.1. Also the Darwin Libc source
- contains the source code for malloc_freezedry and malloc_jumpstart.
- Read that to see what they do. This file was written completely
- from scratch, making use of information from the above sources. */
-
-/* The macOS implementation of unexec makes use of Darwin's `zone'
- memory allocator. All calls to malloc, realloc, and free in Emacs
- are redirected to unexec_malloc, unexec_realloc, and unexec_free in
- this file. When temacs is run, all memory requests are handled in
- the zone EmacsZone. The Darwin memory allocator library calls
- maintain the data structures to manage this zone. Dumping writes
- its contents to data segments of the executable file. When emacs
- is run, the loader recreates the contents of the zone in memory.
- However since the initialization routine of the zone memory
- allocator is run again, this `zone' can no longer be used as a
- heap. That is why emacs uses the ordinary malloc system call to
- allocate memory. Also, when a block of memory needs to be
- reallocated and the new size is larger than the old one, a new
- block must be obtained by malloc and the old contents copied to
- it. */
-
-/* Peculiarity of the Mach-O files generated by ld in macOS
- (possible causes of future bugs if changed).
-
- The file offset of the start of the __TEXT segment is zero. Since
- the Mach header and load commands are located at the beginning of a
- Mach-O file, copying the contents of the __TEXT segment from the
- input file overwrites them in the output file. Despite this,
- unexec works fine as written below because the segment load command
- for __TEXT appears, and is therefore processed, before all other
- load commands except the segment load command for __PAGEZERO, which
- remains unchanged.
-
- Although the file offset of the start of the __TEXT segment is
- zero, none of the sections it contains actually start there. In
- fact, the earliest one starts a few hundred bytes beyond the end of
- the last load command. The linker option -headerpad controls the
- minimum size of this padding. Its setting can be changed in
- s/darwin.h. A value of 0x690, e.g., leaves room for 30 additional
- load commands for the newly created __DATA segments (at 56 bytes
- each). Unexec fails if there is not enough room for these new
- segments.
-
- The __TEXT segment contains the sections __text, __cstring,
- __picsymbol_stub, and __const and the __DATA segment contains the
- sections __data, __la_symbol_ptr, __nl_symbol_ptr, __dyld, __bss,
- and __common. The other segments do not contain any sections.
- These sections are copied from the input file to the output file,
- except for __data, __bss, and __common, which are dumped from
- memory. The types of the sections __bss and __common are changed
- from S_ZEROFILL to S_REGULAR. Note that the number of sections and
- their relative order in the input and output files remain
- unchanged. Otherwise all n_sect fields in the nlist records in the
- symbol table (specified by the LC_SYMTAB load command) will have to
- be changed accordingly.
-*/
-
-#include <config.h>
-
-#include <stdlib.h>
-
-#include "unexec.h"
-#define UNEXMACOSX_C /* Tell lisp.h we want the system malloc, etc. */
-#include "lisp.h"
-#include "sysstdio.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <mach/mach.h>
-#include <mach/vm_map.h>
-#include <mach-o/loader.h>
-#include <mach-o/reloc.h>
-#ifdef HAVE_MALLOC_MALLOC_H
-#include <malloc/malloc.h>
-#else
-#include <objc/malloc.h>
-#endif
-
-#include <assert.h>
-
-/* LC_DATA_IN_CODE is not defined in mach-o/loader.h on Mac OS X 10.7.
- But it is used if we build with "Command Line Tools for Xcode 4.5
- (Mac OS X Lion) - September 2012". */
-#ifndef LC_DATA_IN_CODE
-#define LC_DATA_IN_CODE 0x29 /* table of non-instructions in __text */
-#endif
-
-#ifdef _LP64
-#define mach_header mach_header_64
-#define segment_command segment_command_64
-#undef VM_REGION_BASIC_INFO_COUNT
-#define VM_REGION_BASIC_INFO_COUNT VM_REGION_BASIC_INFO_COUNT_64
-#undef VM_REGION_BASIC_INFO
-#define VM_REGION_BASIC_INFO VM_REGION_BASIC_INFO_64
-#undef LC_SEGMENT
-#define LC_SEGMENT LC_SEGMENT_64
-#define vm_region vm_region_64
-#define section section_64
-#undef MH_MAGIC
-#define MH_MAGIC MH_MAGIC_64
-#endif
-
-#define VERBOSE 1
-
-/* Size of buffer used to copy data from the input file to the output
- file in function unexec_copy. */
-#define UNEXEC_COPY_BUFSZ 1024
-
-/* Regions with memory addresses above this value are assumed to be
- mapped to dynamically loaded libraries and will not be dumped. */
-#define VM_DATA_TOP (20 * 1024 * 1024)
-
-/* Type of an element on the list of regions to be dumped. */
-struct region_t {
- vm_address_t address;
- vm_size_t size;
- vm_prot_t protection;
- vm_prot_t max_protection;
-
- struct region_t *next;
-};
-
-/* Head and tail of the list of regions to be dumped. */
-static struct region_t *region_list_head = 0;
-static struct region_t *region_list_tail = 0;
-
-/* Pointer to array of load commands. */
-static struct load_command **lca;
-
-/* Number of load commands. */
-static int nlc;
-
-/* The highest VM address of segments loaded by the input file.
- Regions with addresses beyond this are assumed to be allocated
- dynamically and thus require dumping. */
-static vm_address_t infile_lc_highest_addr = 0;
-
-/* The lowest file offset used by the all sections in the __TEXT
- segments. This leaves room at the beginning of the file to store
- the Mach-O header. Check this value against header size to ensure
- the added load commands for the new __DATA segments did not
- overwrite any of the sections in the __TEXT segment. */
-static unsigned long text_seg_lowest_offset = 0x10000000;
-
-/* Mach header. */
-static struct mach_header mh;
-
-/* Offset at which the next load command should be written. */
-static unsigned long curr_header_offset = sizeof (struct mach_header);
-
-/* Offset at which the next segment should be written. */
-static unsigned long curr_file_offset = 0;
-
-static unsigned long pagesize;
-#define ROUNDUP_TO_PAGE_BOUNDARY(x) (((x) + pagesize - 1) & ~(pagesize - 1))
-
-static int infd, outfd;
-
-static int in_dumped_exec = 0;
-
-static malloc_zone_t *emacs_zone;
-
-/* file offset of input file's data segment */
-static off_t data_segment_old_fileoff = 0;
-
-static struct segment_command *data_segment_scp;
-
-/* Read N bytes from infd into memory starting at address DEST.
- Return true if successful, false otherwise. */
-static int
-unexec_read (void *dest, size_t n)
-{
- return n == read (infd, dest, n);
-}
-
-/* Write COUNT bytes from memory starting at address SRC to outfd
- starting at offset DEST. Return true if successful, false
- otherwise. */
-static int
-unexec_write (off_t dest, const void *src, size_t count)
-{
- task_t task = mach_task_self();
- if (task == MACH_PORT_NULL || task == MACH_PORT_DEAD)
- return false;
-
- if (lseek (outfd, dest, SEEK_SET) != dest)
- return 0;
-
- /* We use the Mach virtual memory API to read our process memory
- because using src directly would be undefined behavior and fails
- under Address Sanitizer. */
- bool success = false;
- vm_offset_t data;
- mach_msg_type_number_t data_count;
- if (vm_read (task, (uintptr_t) src, count, &data, &data_count)
- == KERN_SUCCESS)
- {
- success =
- write (outfd, (const void *) (uintptr_t) data, data_count) == count;
- vm_deallocate (task, data, data_count);
- }
- return success;
-}
-
-/* Write COUNT bytes of zeros to outfd starting at offset DEST.
- Return true if successful, false otherwise. */
-static int
-unexec_write_zero (off_t dest, size_t count)
-{
- char buf[UNEXEC_COPY_BUFSZ];
- ssize_t bytes;
-
- memset (buf, 0, UNEXEC_COPY_BUFSZ);
- if (lseek (outfd, dest, SEEK_SET) != dest)
- return 0;
-
- while (count > 0)
- {
- bytes = min (count, UNEXEC_COPY_BUFSZ);
- if (write (outfd, buf, bytes) != bytes)
- return 0;
- count -= bytes;
- }
-
- return 1;
-}
-
-/* Copy COUNT bytes from starting offset SRC in infd to starting
- offset DEST in outfd. Return true if successful, false
- otherwise. */
-static int
-unexec_copy (off_t dest, off_t src, ssize_t count)
-{
- ssize_t bytes_read;
- ssize_t bytes_to_read;
-
- char buf[UNEXEC_COPY_BUFSZ];
-
- if (lseek (infd, src, SEEK_SET) != src)
- return 0;
-
- if (lseek (outfd, dest, SEEK_SET) != dest)
- return 0;
-
- while (count > 0)
- {
- bytes_to_read = min (count, UNEXEC_COPY_BUFSZ);
- bytes_read = read (infd, buf, bytes_to_read);
- if (bytes_read <= 0)
- return 0;
- if (write (outfd, buf, bytes_read) != bytes_read)
- return 0;
- count -= bytes_read;
- }
-
- return 1;
-}
-
-/* Debugging and informational messages routines. */
-
-static _Noreturn void
-unexec_error (const char *format, ...)
-{
- va_list ap;
-
- va_start (ap, format);
- fputs ("unexec: ", stderr);
- vfprintf (stderr, format, ap);
- putc ('\n', stderr);
- va_end (ap);
- exit (1);
-}
-
-static void
-print_prot (vm_prot_t prot)
-{
- if (prot == VM_PROT_NONE)
- printf ("none");
- else
- {
- putchar (prot & VM_PROT_READ ? 'r' : ' ');
- putchar (prot & VM_PROT_WRITE ? 'w' : ' ');
- putchar (prot & VM_PROT_EXECUTE ? 'x' : ' ');
- putchar (' ');
- }
-}
-
-static void
-print_region (vm_address_t address, vm_size_t size, vm_prot_t prot,
- vm_prot_t max_prot)
-{
- printf ("%#10lx %#8lx ", (long) address, (long) size);
- print_prot (prot);
- putchar (' ');
- print_prot (max_prot);
- putchar ('\n');
-}
-
-static void
-print_region_list (void)
-{
- struct region_t *r;
-
- printf (" address size prot maxp\n");
-
- for (r = region_list_head; r; r = r->next)
- print_region (r->address, r->size, r->protection, r->max_protection);
-}
-
-/* Build the list of regions that need to be dumped. Regions with
- addresses above VM_DATA_TOP are omitted. Adjacent regions with
- identical protection are merged. Note that non-writable regions
- cannot be omitted because they some regions created at run time are
- read-only. */
-static void
-build_region_list (void)
-{
- task_t target_task = mach_task_self ();
- vm_address_t address = (vm_address_t) 0;
- vm_size_t size;
- struct vm_region_basic_info info;
- mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
- mach_port_t object_name;
- struct region_t *r;
-
-#if VERBOSE
- printf ("--- List of All Regions ---\n");
- printf (" address size prot maxp\n");
-#endif
-
- while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO,
- (vm_region_info_t) &info, &info_count, &object_name)
- == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT)
- {
- /* Done when we reach addresses of shared libraries, which are
- loaded in high memory. */
- if (address >= VM_DATA_TOP)
- break;
-
-#if VERBOSE
- print_region (address, size, info.protection, info.max_protection);
-#endif
-
- /* If a region immediately follows the previous one (the one
- most recently added to the list) and has identical
- protection, merge it with the latter. Otherwise create a
- new list element for it. */
- if (region_list_tail
- && info.protection == region_list_tail->protection
- && info.max_protection == region_list_tail->max_protection
- && region_list_tail->address + region_list_tail->size == address)
- {
- region_list_tail->size += size;
- }
- else
- {
- r = malloc (sizeof *r);
-
- if (!r)
- unexec_error ("cannot allocate region structure");
-
- r->address = address;
- r->size = size;
- r->protection = info.protection;
- r->max_protection = info.max_protection;
-
- r->next = 0;
- if (region_list_head == 0)
- {
- region_list_head = r;
- region_list_tail = r;
- }
- else
- {
- region_list_tail->next = r;
- region_list_tail = r;
- }
-
- /* Deallocate (unused) object name returned by
- vm_region. */
- if (object_name != MACH_PORT_NULL)
- mach_port_deallocate (target_task, object_name);
- }
-
- address += size;
- }
-
- printf ("--- List of Regions to be Dumped ---\n");
- print_region_list ();
-}
-
-
-#define MAX_UNEXEC_REGIONS 400
-
-static int num_unexec_regions;
-typedef struct {
- vm_range_t range;
- vm_size_t filesize;
-} unexec_region_info;
-static unexec_region_info unexec_regions[MAX_UNEXEC_REGIONS];
-
-static void
-unexec_regions_recorder (task_t task, void *rr, unsigned type,
- vm_range_t *ranges, unsigned num)
-{
- vm_address_t p;
- vm_size_t filesize;
-
- while (num && num_unexec_regions < MAX_UNEXEC_REGIONS)
- {
- /* Subtract the size of trailing null bytes from filesize. It
- can be smaller than vmsize in segment commands. In such a
- case, trailing bytes are initialized with zeros. */
- for (p = ranges->address + ranges->size; p > ranges->address; p--)
- if (*(((char *) p)-1))
- break;
- filesize = p - ranges->address;
-
- unexec_regions[num_unexec_regions].filesize = filesize;
- unexec_regions[num_unexec_regions++].range = *ranges;
- printf ("%#10lx (sz: %#8lx/%#8lx)\n", (long) (ranges->address),
- (long) filesize, (long) (ranges->size));
- ranges++; num--;
- }
-}
-
-static kern_return_t
-unexec_reader (task_t task, vm_address_t address, vm_size_t size, void **ptr)
-{
- *ptr = (void *) address;
- return KERN_SUCCESS;
-}
-
-static void
-find_emacs_zone_regions (void)
-{
- num_unexec_regions = 0;
-
- emacs_zone->introspect->enumerator (mach_task_self (), 0,
- MALLOC_PTR_REGION_RANGE_TYPE
- | MALLOC_ADMIN_REGION_RANGE_TYPE,
- (vm_address_t) emacs_zone,
- unexec_reader,
- unexec_regions_recorder);
-
- if (num_unexec_regions == MAX_UNEXEC_REGIONS)
- unexec_error ("find_emacs_zone_regions: too many regions");
-}
-
-static int
-unexec_regions_sort_compare (const void *a, const void *b)
-{
- vm_address_t aa = ((unexec_region_info *) a)->range.address;
- vm_address_t bb = ((unexec_region_info *) b)->range.address;
-
- if (aa < bb)
- return -1;
- else if (aa > bb)
- return 1;
- else
- return 0;
-}
-
-static void
-unexec_regions_merge (void)
-{
- qsort (unexec_regions, num_unexec_regions, sizeof (unexec_regions[0]),
- &unexec_regions_sort_compare);
-
- /* Align each region start address to a page boundary. */
- for (unexec_region_info *cur = unexec_regions;
- cur < unexec_regions + num_unexec_regions; cur++)
- {
- vm_size_t padsize = cur->range.address & (pagesize - 1);
- if (padsize)
- {
- cur->range.address -= padsize;
- cur->range.size += padsize;
- cur->filesize += padsize;
-
- unexec_region_info *prev = cur == unexec_regions ? NULL : cur - 1;
- if (prev
- && prev->range.address + prev->range.size > cur->range.address)
- {
- prev->range.size = cur->range.address - prev->range.address;
- if (prev->filesize > prev->range.size)
- prev->filesize = prev->range.size;
- }
- }
- }
-
- int n = 0;
- unexec_region_info r = unexec_regions[0];
- for (int i = 1; i < num_unexec_regions; i++)
- {
- if (r.range.address + r.range.size == unexec_regions[i].range.address
- && r.range.size - r.filesize < 2 * pagesize)
- {
- r.filesize = r.range.size + unexec_regions[i].filesize;
- r.range.size += unexec_regions[i].range.size;
- }
- else
- {
- unexec_regions[n++] = r;
- r = unexec_regions[i];
- }
- }
- unexec_regions[n++] = r;
- num_unexec_regions = n;
-}
-
-
-/* More informational messages routines. */
-
-static void
-print_load_command_name (int lc)
-{
- switch (lc)
- {
- case LC_SEGMENT:
-#ifndef _LP64
- printf ("LC_SEGMENT ");
-#else
- printf ("LC_SEGMENT_64 ");
-#endif
- break;
- case LC_LOAD_DYLINKER:
- printf ("LC_LOAD_DYLINKER ");
- break;
- case LC_LOAD_DYLIB:
- printf ("LC_LOAD_DYLIB ");
- break;
- case LC_SYMTAB:
- printf ("LC_SYMTAB ");
- break;
- case LC_DYSYMTAB:
- printf ("LC_DYSYMTAB ");
- break;
- case LC_UNIXTHREAD:
- printf ("LC_UNIXTHREAD ");
- break;
- case LC_PREBOUND_DYLIB:
- printf ("LC_PREBOUND_DYLIB");
- break;
- case LC_TWOLEVEL_HINTS:
- printf ("LC_TWOLEVEL_HINTS");
- break;
-#ifdef LC_UUID
- case LC_UUID:
- printf ("LC_UUID ");
- break;
-#endif
-#ifdef LC_DYLD_INFO
- case LC_DYLD_INFO:
- printf ("LC_DYLD_INFO ");
- break;
- case LC_DYLD_INFO_ONLY:
- printf ("LC_DYLD_INFO_ONLY");
- break;
-#endif
-#ifdef LC_VERSION_MIN_MACOSX
- case LC_VERSION_MIN_MACOSX:
- printf ("LC_VERSION_MIN_MACOSX");
- break;
-#endif
-#ifdef LC_FUNCTION_STARTS
- case LC_FUNCTION_STARTS:
- printf ("LC_FUNCTION_STARTS");
- break;
-#endif
-#ifdef LC_MAIN
- case LC_MAIN:
- printf ("LC_MAIN ");
- break;
-#endif
-#ifdef LC_DATA_IN_CODE
- case LC_DATA_IN_CODE:
- printf ("LC_DATA_IN_CODE ");
- break;
-#endif
-#ifdef LC_SOURCE_VERSION
- case LC_SOURCE_VERSION:
- printf ("LC_SOURCE_VERSION");
- break;
-#endif
-#ifdef LC_DYLIB_CODE_SIGN_DRS
- case LC_DYLIB_CODE_SIGN_DRS:
- printf ("LC_DYLIB_CODE_SIGN_DRS");
- break;
-#endif
- default:
- printf ("unknown ");
- }
-}
-
-static void
-print_load_command (struct load_command *lc)
-{
- print_load_command_name (lc->cmd);
- printf ("%8d", lc->cmdsize);
-
- if (lc->cmd == LC_SEGMENT)
- {
- struct segment_command *scp;
- struct section *sectp;
- int j;
-
- scp = (struct segment_command *) lc;
- printf (" %-16.16s %#10lx %#8lx\n",
- scp->segname, (long) (scp->vmaddr), (long) (scp->vmsize));
-
- sectp = (struct section *) (scp + 1);
- for (j = 0; j < scp->nsects; j++)
- {
- printf (" %-16.16s %#10lx %#8lx\n",
- sectp->sectname, (long) (sectp->addr), (long) (sectp->size));
- sectp++;
- }
- }
- else
- printf ("\n");
-}
-
-/* Read header and load commands from input file. Store the latter in
- the global array lca. Store the total number of load commands in
- global variable nlc. */
-static void
-read_load_commands (void)
-{
- int i;
-
- if (!unexec_read (&mh, sizeof (struct mach_header)))
- unexec_error ("cannot read mach-o header");
-
- if (mh.magic != MH_MAGIC)
- unexec_error ("input file not in Mach-O format");
-
- if (mh.filetype != MH_EXECUTE)
- unexec_error ("input Mach-O file is not an executable object file");
-
-#if VERBOSE
- printf ("--- Header Information ---\n");
- printf ("Magic = 0x%08x\n", mh.magic);
- printf ("CPUType = %d\n", mh.cputype);
- printf ("CPUSubType = %d\n", mh.cpusubtype);
- printf ("FileType = 0x%x\n", mh.filetype);
- printf ("NCmds = %d\n", mh.ncmds);
- printf ("SizeOfCmds = %d\n", mh.sizeofcmds);
- printf ("Flags = 0x%08x\n", mh.flags);
-#endif
-
- nlc = mh.ncmds;
- lca = malloc (nlc * sizeof *lca);
-
- for (i = 0; i < nlc; i++)
- {
- struct load_command lc;
- /* Load commands are variable-size: so read the command type and
- size first and then read the rest. */
- if (!unexec_read (&lc, sizeof (struct load_command)))
- unexec_error ("cannot read load command");
- lca[i] = malloc (lc.cmdsize);
- memcpy (lca[i], &lc, sizeof (struct load_command));
- if (!unexec_read (lca[i] + 1, lc.cmdsize - sizeof (struct load_command)))
- unexec_error ("cannot read content of load command");
- if (lc.cmd == LC_SEGMENT)
- {
- struct segment_command *scp = (struct segment_command *) lca[i];
-
- if (scp->vmaddr + scp->vmsize > infile_lc_highest_addr)
- infile_lc_highest_addr = scp->vmaddr + scp->vmsize;
-
- if (strncmp (scp->segname, SEG_TEXT, 16) == 0)
- {
- struct section *sectp = (struct section *) (scp + 1);
- int j;
-
- for (j = 0; j < scp->nsects; j++)
- if (sectp->offset < text_seg_lowest_offset)
- text_seg_lowest_offset = sectp->offset;
- }
- }
- }
-
- printf ("Highest address of load commands in input file: %#8lx\n",
- (unsigned long)infile_lc_highest_addr);
-
- printf ("Lowest offset of all sections in __TEXT segment: %#8lx\n",
- text_seg_lowest_offset);
-
- printf ("--- List of Load Commands in Input File ---\n");
- printf ("# cmd cmdsize name address size\n");
-
- for (i = 0; i < nlc; i++)
- {
- printf ("%1d ", i);
- print_load_command (lca[i]);
- }
-}
-
-/* Copy a LC_SEGMENT load command other than the __DATA segment from
- the input file to the output file, adjusting the file offset of the
- segment and the file offsets of sections contained in it. */
-static void
-copy_segment (struct load_command *lc)
-{
- struct segment_command *scp = (struct segment_command *) lc;
- unsigned long old_fileoff = scp->fileoff;
- struct section *sectp;
- int j;
-
- scp->fileoff = curr_file_offset;
-
- sectp = (struct section *) (scp + 1);
- for (j = 0; j < scp->nsects; j++)
- {
- sectp->offset += curr_file_offset - old_fileoff;
- sectp++;
- }
-
- printf ("Writing segment %-16.16s @ %#8lx (%#8lx/%#8lx @ %#10lx)\n",
- scp->segname, (long) (scp->fileoff), (long) (scp->filesize),
- (long) (scp->vmsize), (long) (scp->vmaddr));
-
- if (!unexec_copy (scp->fileoff, old_fileoff, scp->filesize))
- unexec_error ("cannot copy segment from input to output file");
- curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (scp->filesize);
-
- if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
- unexec_error ("cannot write load command to header");
-
- curr_header_offset += lc->cmdsize;
-}
-
-/* Copy a LC_SEGMENT load command for the __DATA segment in the input
- file to the output file. We assume that only one such segment load
- command exists in the input file and it contains the sections
- __data, __bss, __common, __la_symbol_ptr, __nl_symbol_ptr, and
- __dyld. The first three of these should be dumped from memory and
- the rest should be copied from the input file. Note that the
- sections __bss and __common contain no data in the input file
- because their flag fields have the value S_ZEROFILL. Dumping these
- from memory makes it necessary to adjust file offset fields in
- subsequently dumped load commands. Then, create new __DATA segment
- load commands for regions on the region list other than the one
- corresponding to the __DATA segment in the input file. */
-static void
-copy_data_segment (struct load_command *lc)
-{
- struct segment_command *scp = (struct segment_command *) lc;
- struct section *sectp;
- int j;
- unsigned long header_offset, old_file_offset;
-
- /* The new filesize of the segment is set to its vmsize because data
- blocks for segments must start at region boundaries. Note that
- this may leave unused locations at the end of the segment data
- block because the total of the sizes of all sections in the
- segment is generally smaller than vmsize. */
- scp->filesize = scp->vmsize;
-
- printf ("Writing segment %-16.16s @ %#8lx (%#8lx/%#8lx @ %#10lx)\n",
- scp->segname, curr_file_offset, (long)(scp->filesize),
- (long)(scp->vmsize), (long) (scp->vmaddr));
-
- /* Offsets in the output file for writing the next section structure
- and segment data block, respectively. */
- header_offset = curr_header_offset + sizeof (struct segment_command);
-
- sectp = (struct section *) (scp + 1);
- for (j = 0; j < scp->nsects; j++)
- {
- old_file_offset = sectp->offset;
- sectp->offset = sectp->addr - scp->vmaddr + curr_file_offset;
- /* The __data section is dumped from memory. The __bss and
- __common sections are also dumped from memory but their flag
- fields require changing (from S_ZEROFILL to S_REGULAR). The
- other three kinds of sections are just copied from the input
- file. */
- if (strncmp (sectp->sectname, SECT_DATA, 16) == 0)
- {
- unsigned long my_size;
-
- /* The __data section is basically dumped from memory. But
- initialized data in statically linked libraries are
- copied from the input file. In particular,
- add_image_hook.names and add_image_hook.pointers stored
- by libarclite_macosx.a, are restored so that they will be
- reinitialized when the dumped binary is executed. */
- my_size = (unsigned long)my_edata - sectp->addr;
- if (!(sectp->addr <= (unsigned long)my_edata
- && my_size <= sectp->size))
- unexec_error ("my_edata is not in section %s", SECT_DATA);
- if (!unexec_write (sectp->offset, (void *) sectp->addr, my_size))
- unexec_error ("cannot write section %s", SECT_DATA);
- if (!unexec_copy (sectp->offset + my_size, old_file_offset + my_size,
- sectp->size - my_size))
- unexec_error ("cannot copy section %s", SECT_DATA);
- if (!unexec_write (header_offset, sectp, sizeof (struct section)))
- unexec_error ("cannot write section %s's header", SECT_DATA);
- }
- else if (strncmp (sectp->sectname, SECT_COMMON, 16) == 0)
- {
- sectp->flags = S_REGULAR;
- if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
- unexec_error ("cannot write section %.16s", sectp->sectname);
- if (!unexec_write (header_offset, sectp, sizeof (struct section)))
- unexec_error ("cannot write section %.16s's header", sectp->sectname);
- }
- else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0)
- {
- unsigned long my_size;
-
- sectp->flags = S_REGULAR;
-
- /* Clear uninitialized local variables in statically linked
- libraries. In particular, function pointers stored by
- libSystemStub.a, which is introduced in Mac OS X 10.4 for
- binary compatibility with respect to long double, are
- cleared so that they will be reinitialized when the
- dumped binary is executed on other versions of OS. */
- my_size = (unsigned long)my_endbss_static - sectp->addr;
- if (!(sectp->addr <= (unsigned long)my_endbss_static
- && my_size <= sectp->size))
- unexec_error ("my_endbss_static is not in section %.16s",
- sectp->sectname);
- if (!unexec_write (sectp->offset, (void *) sectp->addr, my_size))
- unexec_error ("cannot write section %.16s", sectp->sectname);
- if (!unexec_write_zero (sectp->offset + my_size,
- sectp->size - my_size))
- unexec_error ("cannot write section %.16s", sectp->sectname);
- if (!unexec_write (header_offset, sectp, sizeof (struct section)))
- unexec_error ("cannot write section %.16s's header", sectp->sectname);
- }
- else if (strncmp (sectp->sectname, "__bss", 5) == 0
- || strncmp (sectp->sectname, "__pu_bss", 8) == 0)
- {
- sectp->flags = S_REGULAR;
-
- /* These sections are produced by GCC 4.6+.
-
- FIXME: We possibly ought to clear uninitialized local
- variables in statically linked libraries like for
- SECT_BSS (__bss) above, but setting up the markers we
- need in lastfile.c would be rather messy. See
- darwin_output_aligned_bss () in gcc/config/darwin.c for
- the root of the problem, keeping in mind that the
- sections are numbered by their alignment in GCC 4.6, but
- by log2(alignment) in GCC 4.7. */
-
- if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
- unexec_error ("cannot copy section %.16s", sectp->sectname);
- if (!unexec_write (header_offset, sectp, sizeof (struct section)))
- unexec_error ("cannot write section %.16s's header", sectp->sectname);
- }
- else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0
- || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0
- || strncmp (sectp->sectname, "__got", 16) == 0
- || strncmp (sectp->sectname, "__la_sym_ptr2", 16) == 0
- || strncmp (sectp->sectname, "__dyld", 16) == 0
- || strncmp (sectp->sectname, "__const", 16) == 0
- || strncmp (sectp->sectname, "__cfstring", 16) == 0
- || strncmp (sectp->sectname, "__gcc_except_tab", 16) == 0
- || strncmp (sectp->sectname, "__program_vars", 16) == 0
- || strncmp (sectp->sectname, "__mod_init_func", 16) == 0
- || strncmp (sectp->sectname, "__mod_term_func", 16) == 0
- || strncmp (sectp->sectname, "__static_data", 16) == 0
- || strncmp (sectp->sectname, "__objc_", 7) == 0)
- {
- if (!unexec_copy (sectp->offset, old_file_offset, sectp->size))
- unexec_error ("cannot copy section %.16s", sectp->sectname);
- if (!unexec_write (header_offset, sectp, sizeof (struct section)))
- unexec_error ("cannot write section %.16s's header", sectp->sectname);
- }
- else
- unexec_error ("unrecognized section %.16s in __DATA segment",
- sectp->sectname);
-
- printf (" section %-16.16s at %#8lx - %#8lx (sz: %#8lx)\n",
- sectp->sectname, (long) (sectp->offset),
- (long) (sectp->offset + sectp->size), (long) (sectp->size));
-
- header_offset += sizeof (struct section);
- sectp++;
- }
-
- curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (scp->filesize);
-
- if (!unexec_write (curr_header_offset, scp, sizeof (struct segment_command)))
- unexec_error ("cannot write header of __DATA segment");
- curr_header_offset += lc->cmdsize;
-
- /* Create new __DATA segment load commands for regions on the region
- list that do not corresponding to any segment load commands in
- the input file.
- */
- for (j = 0; j < num_unexec_regions; j++)
- {
- struct segment_command sc;
-
- sc.cmd = LC_SEGMENT;
- sc.cmdsize = sizeof (struct segment_command);
- strncpy (sc.segname, SEG_DATA, 16);
- sc.vmaddr = unexec_regions[j].range.address;
- sc.vmsize = unexec_regions[j].range.size;
- sc.fileoff = curr_file_offset;
- sc.filesize = unexec_regions[j].filesize;
- sc.maxprot = VM_PROT_READ | VM_PROT_WRITE;
- sc.initprot = VM_PROT_READ | VM_PROT_WRITE;
- sc.nsects = 0;
- sc.flags = 0;
-
- printf ("Writing segment %-16.16s @ %#8lx (%#8lx/%#8lx @ %#10lx)\n",
- sc.segname, (long) (sc.fileoff), (long) (sc.filesize),
- (long) (sc.vmsize), (long) (sc.vmaddr));
-
- if (!unexec_write (sc.fileoff, (void *) sc.vmaddr, sc.filesize))
- unexec_error ("cannot write new __DATA segment");
- curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (sc.filesize);
-
- if (!unexec_write (curr_header_offset, &sc, sc.cmdsize))
- unexec_error ("cannot write new __DATA segment's header");
- curr_header_offset += sc.cmdsize;
- mh.ncmds++;
- }
-}
-
-/* Copy a LC_SYMTAB load command from the input file to the output
- file, adjusting the file offset fields. */
-static void
-copy_symtab (struct load_command *lc, long delta)
-{
- struct symtab_command *stp = (struct symtab_command *) lc;
-
- stp->symoff += delta;
- stp->stroff += delta;
-
- printf ("Writing LC_SYMTAB command\n");
-
- if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
- unexec_error ("cannot write symtab command to header");
-
- curr_header_offset += lc->cmdsize;
-}
-
-/* Fix up relocation entries. */
-static void
-unrelocate (const char *name, off_t reloff, int nrel, vm_address_t base)
-{
- int i, unreloc_count;
- struct relocation_info reloc_info;
- struct scattered_relocation_info *sc_reloc_info
- = (struct scattered_relocation_info *) &reloc_info;
- vm_address_t location;
-
- for (unreloc_count = 0, i = 0; i < nrel; i++)
- {
- if (lseek (infd, reloff, L_SET) != reloff)
- unexec_error ("unrelocate: %s:%d cannot seek to reloc_info", name, i);
- if (!unexec_read (&reloc_info, sizeof (reloc_info)))
- unexec_error ("unrelocate: %s:%d cannot read reloc_info", name, i);
- reloff += sizeof (reloc_info);
-
- if (sc_reloc_info->r_scattered == 0)
- switch (reloc_info.r_type)
- {
- case GENERIC_RELOC_VANILLA:
- location = base + reloc_info.r_address;
- if (location >= data_segment_scp->vmaddr
- && location < (data_segment_scp->vmaddr
- + data_segment_scp->vmsize))
- {
- off_t src_off = data_segment_old_fileoff
- + (location - data_segment_scp->vmaddr);
- off_t dst_off = data_segment_scp->fileoff
- + (location - data_segment_scp->vmaddr);
-
- if (!unexec_copy (dst_off, src_off, 1 << reloc_info.r_length))
- unexec_error ("unrelocate: %s:%d cannot copy original value",
- name, i);
- unreloc_count++;
- }
- break;
- default:
- unexec_error ("unrelocate: %s:%d cannot handle type = %d",
- name, i, reloc_info.r_type);
- }
- else
- unexec_error ("unrelocate: %s:%d cannot handle scattered type = %d",
- name, i, sc_reloc_info->r_type);
- }
-
- if (nrel > 0)
- printf ("Fixed up %d/%d %s relocation entries in data segment.\n",
- unreloc_count, nrel, name);
-}
-
-/* Copy a LC_DYSYMTAB load command from the input file to the output
- file, adjusting the file offset fields. */
-static void
-copy_dysymtab (struct load_command *lc, long delta)
-{
- struct dysymtab_command *dstp = (struct dysymtab_command *) lc;
- vm_address_t base;
-
-#ifdef _LP64
- /* First writable segment address. */
- base = data_segment_scp->vmaddr;
-#else
- /* First segment address in the file (unless MH_SPLIT_SEGS set). */
- base = 0;
-#endif
-
- unrelocate ("local", dstp->locreloff, dstp->nlocrel, base);
- unrelocate ("external", dstp->extreloff, dstp->nextrel, base);
-
- if (dstp->nextrel > 0) {
- dstp->extreloff += delta;
- }
-
- if (dstp->nlocrel > 0) {
- dstp->locreloff += delta;
- }
-
- if (dstp->nindirectsyms > 0)
- dstp->indirectsymoff += delta;
-
- printf ("Writing LC_DYSYMTAB command\n");
-
- if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
- unexec_error ("cannot write symtab command to header");
-
- curr_header_offset += lc->cmdsize;
-}
-
-/* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output
- file, adjusting the file offset fields. */
-static void
-copy_twolevelhints (struct load_command *lc, long delta)
-{
- struct twolevel_hints_command *tlhp = (struct twolevel_hints_command *) lc;
-
- if (tlhp->nhints > 0) {
- tlhp->offset += delta;
- }
-
- printf ("Writing LC_TWOLEVEL_HINTS command\n");
-
- if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
- unexec_error ("cannot write two level hint command to header");
-
- curr_header_offset += lc->cmdsize;
-}
-
-#ifdef LC_DYLD_INFO
-/* Copy a LC_DYLD_INFO(_ONLY) load command from the input file to the output
- file, adjusting the file offset fields. */
-static void
-copy_dyld_info (struct load_command *lc, long delta)
-{
- struct dyld_info_command *dip = (struct dyld_info_command *) lc;
-
- if (dip->rebase_off > 0)
- dip->rebase_off += delta;
- if (dip->bind_off > 0)
- dip->bind_off += delta;
- if (dip->weak_bind_off > 0)
- dip->weak_bind_off += delta;
- if (dip->lazy_bind_off > 0)
- dip->lazy_bind_off += delta;
- if (dip->export_off > 0)
- dip->export_off += delta;
-
- printf ("Writing ");
- print_load_command_name (lc->cmd);
- printf (" command\n");
-
- if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
- unexec_error ("cannot write dyld info command to header");
-
- curr_header_offset += lc->cmdsize;
-}
-#endif
-
-#ifdef LC_FUNCTION_STARTS
-/* Copy a LC_FUNCTION_STARTS/LC_DATA_IN_CODE/LC_DYLIB_CODE_SIGN_DRS
- load command from the input file to the output file, adjusting the
- data offset field. */
-static void
-copy_linkedit_data (struct load_command *lc, long delta)
-{
- struct linkedit_data_command *ldp = (struct linkedit_data_command *) lc;
-
- if (ldp->dataoff > 0)
- ldp->dataoff += delta;
-
- printf ("Writing ");
- print_load_command_name (lc->cmd);
- printf (" command\n");
-
- if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
- unexec_error ("cannot write linkedit data command to header");
-
- curr_header_offset += lc->cmdsize;
-}
-#endif
-
-/* Copy other kinds of load commands from the input file to the output
- file, ones that do not require adjustments of file offsets. */
-static void
-copy_other (struct load_command *lc)
-{
- printf ("Writing ");
- print_load_command_name (lc->cmd);
- printf (" command\n");
-
- if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
- unexec_error ("cannot write symtab command to header");
-
- curr_header_offset += lc->cmdsize;
-}
-
-/* Loop through all load commands and dump them. Then write the Mach
- header. */
-static void
-dump_it (void)
-{
- int i;
- long linkedit_delta = 0;
-
- printf ("--- Load Commands written to Output File ---\n");
-
- for (i = 0; i < nlc; i++)
- switch (lca[i]->cmd)
- {
- case LC_SEGMENT:
- {
- struct segment_command *scp = (struct segment_command *) lca[i];
- if (strncmp (scp->segname, SEG_DATA, 16) == 0)
- {
- /* save data segment file offset and segment_command for
- unrelocate */
- if (data_segment_old_fileoff)
- unexec_error ("cannot handle multiple DATA segments"
- " in input file");
- data_segment_old_fileoff = scp->fileoff;
- data_segment_scp = scp;
-
- copy_data_segment (lca[i]);
- }
- else
- {
- if (strncmp (scp->segname, SEG_LINKEDIT, 16) == 0)
- {
- if (linkedit_delta)
- unexec_error ("cannot handle multiple LINKEDIT segments"
- " in input file");
- linkedit_delta = curr_file_offset - scp->fileoff;
- }
-
- copy_segment (lca[i]);
- }
- }
- break;
- case LC_SYMTAB:
- copy_symtab (lca[i], linkedit_delta);
- break;
- case LC_DYSYMTAB:
- copy_dysymtab (lca[i], linkedit_delta);
- break;
- case LC_TWOLEVEL_HINTS:
- copy_twolevelhints (lca[i], linkedit_delta);
- break;
-#ifdef LC_DYLD_INFO
- case LC_DYLD_INFO:
- case LC_DYLD_INFO_ONLY:
- copy_dyld_info (lca[i], linkedit_delta);
- break;
-#endif
-#ifdef LC_FUNCTION_STARTS
- case LC_FUNCTION_STARTS:
-#ifdef LC_DATA_IN_CODE
- case LC_DATA_IN_CODE:
-#endif
-#ifdef LC_DYLIB_CODE_SIGN_DRS
- case LC_DYLIB_CODE_SIGN_DRS:
-#endif
- copy_linkedit_data (lca[i], linkedit_delta);
- break;
-#endif
- default:
- copy_other (lca[i]);
- break;
- }
-
- if (curr_header_offset > text_seg_lowest_offset)
- unexec_error ("not enough room for load commands for new __DATA segments"
- " (increase headerpad_extra in configure.in to at least %lX)",
- num_unexec_regions * sizeof (struct segment_command));
-
- printf ("%ld unused bytes follow Mach-O header\n",
- text_seg_lowest_offset - curr_header_offset);
-
- mh.sizeofcmds = curr_header_offset - sizeof (struct mach_header);
- if (!unexec_write (0, &mh, sizeof (struct mach_header)))
- unexec_error ("cannot write final header contents");
-}
-
-/* Take a snapshot of Emacs and make a Mach-O format executable file
- from it. The file names of the output and input files are outfile
- and infile, respectively. The three other parameters are
- ignored. */
-void
-unexec (const char *outfile, const char *infile)
-{
- if (in_dumped_exec)
- unexec_error ("Unexec from a dumped executable is not supported.");
-
- pagesize = getpagesize ();
- infd = emacs_open (infile, O_RDONLY, 0);
- if (infd < 0)
- {
- unexec_error ("%s: %s", infile, strerror (errno));
- }
-
- outfd = emacs_open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0777);
- if (outfd < 0)
- {
- emacs_close (infd);
- unexec_error ("%s: %s", outfile, strerror (errno));
- }
-
- build_region_list ();
- read_load_commands ();
-
- find_emacs_zone_regions ();
- unexec_regions_merge ();
-
- in_dumped_exec = 1;
-
- dump_it ();
-
- emacs_close (outfd);
-}
-
-
-void
-unexec_init_emacs_zone (void)
-{
- emacs_zone = malloc_create_zone (0, 0);
- malloc_set_zone_name (emacs_zone, "EmacsZone");
-}
-
-#ifndef MACOSX_MALLOC_MULT16
-#define MACOSX_MALLOC_MULT16 1
-#endif
-
-typedef struct unexec_malloc_header {
- union {
- char c[8];
- size_t size;
- } u;
-} unexec_malloc_header_t;
-
-#if MACOSX_MALLOC_MULT16
-
-#define ptr_in_unexec_regions(p) ((((vm_address_t) (p)) & 8) != 0)
-
-#else
-
-int
-ptr_in_unexec_regions (void *ptr)
-{
- int i;
-
- for (i = 0; i < num_unexec_regions; i++)
- if ((vm_address_t) ptr - unexec_regions[i].range.address
- < unexec_regions[i].range.size)
- return 1;
-
- return 0;
-}
-
-#endif
-
-void *
-unexec_malloc (size_t size)
-{
- if (in_dumped_exec)
- {
- void *p;
-
- p = malloc (size);
-#if MACOSX_MALLOC_MULT16
- assert (((vm_address_t) p % 16) == 0);
-#endif
- return p;
- }
- else
- {
- unexec_malloc_header_t *ptr;
-
- ptr = (unexec_malloc_header_t *)
- malloc_zone_malloc (emacs_zone, size + sizeof (unexec_malloc_header_t));
- ptr->u.size = size;
- ptr++;
-#if MACOSX_MALLOC_MULT16
- assert (((vm_address_t) ptr % 16) == 8);
-#endif
- return (void *) ptr;
- }
-}
-
-void *
-unexec_realloc (void *old_ptr, size_t new_size)
-{
- if (in_dumped_exec)
- {
- void *p;
-
- if (ptr_in_unexec_regions (old_ptr))
- {
- size_t old_size = ((unexec_malloc_header_t *) old_ptr)[-1].u.size;
- size_t size = min (new_size, old_size);
-
- p = malloc (new_size);
- if (size)
- memcpy (p, old_ptr, size);
- }
- else
- {
- p = realloc (old_ptr, new_size);
- }
-#if MACOSX_MALLOC_MULT16
- assert (((vm_address_t) p % 16) == 0);
-#endif
- return p;
- }
- else
- {
- unexec_malloc_header_t *ptr;
-
- ptr = (unexec_malloc_header_t *)
- malloc_zone_realloc (emacs_zone, (unexec_malloc_header_t *) old_ptr - 1,
- new_size + sizeof (unexec_malloc_header_t));
- ptr->u.size = new_size;
- ptr++;
-#if MACOSX_MALLOC_MULT16
- assert (((vm_address_t) ptr % 16) == 8);
-#endif
- return (void *) ptr;
- }
-}
-
-void
-unexec_free (void *ptr)
-{
- if (ptr == NULL)
- return;
- if (in_dumped_exec)
- {
- if (!ptr_in_unexec_regions (ptr))
- free (ptr);
- }
- else
- malloc_zone_free (emacs_zone, (unexec_malloc_header_t *) ptr - 1);
-}
diff --git a/src/unexsol.c b/src/unexsol.c
deleted file mode 100644
index 0f84099d39e..00000000000
--- a/src/unexsol.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Trivial unexec for Solaris. */
-
-#include <config.h>
-#include "unexec.h"
-
-#include <dlfcn.h>
-
-#include "lisp.h"
-#include "buffer.h"
-#include "coding.h"
-
-void
-unexec (const char *new_name, const char *old_name)
-{
- Lisp_Object data;
- Lisp_Object errstring;
-
- if (! dldump (0, new_name, RTLD_MEMORY))
- return;
-
- data = list1 (build_string (new_name));
- synchronize_system_messages_locale ();
- errstring = code_convert_string_norecord (build_string (dlerror ()),
- Vlocale_coding_system, 0);
-
- xsignal (Qfile_error,
- Fcons (build_string ("Cannot unexec"), Fcons (errstring, data)));
-}
diff --git a/src/unexw32.c b/src/unexw32.c
deleted file mode 100644
index fd01e04cf18..00000000000
--- a/src/unexw32.c
+++ /dev/null
@@ -1,684 +0,0 @@
-/* unexec for GNU Emacs on Windows NT.
- Copyright (C) 1994, 2001-2025 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
-/*
- Geoff Voelker (voelker@cs.washington.edu) 8-12-94
-*/
-
-#include <config.h>
-#include "unexec.h"
-#include "lisp.h"
-#include "w32common.h"
-#include "w32.h"
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <time.h>
-#include <windows.h>
-
-/* Include relevant definitions from IMAGEHLP.H, which can be found
- in \\win32sdk\mstools\samples\image\include\imagehlp.h. */
-
-PIMAGE_NT_HEADERS (__stdcall * pfnCheckSumMappedFile) (LPVOID BaseAddress,
- DWORD FileLength,
- LPDWORD HeaderSum,
- LPDWORD CheckSum);
-
-extern char my_begdata[];
-extern char my_begbss[];
-extern char *my_begbss_static;
-
-#include "w32heap.h"
-
-void get_section_info (file_data *p_file);
-void copy_executable_and_dump_data (file_data *, file_data *);
-void dump_bss_and_heap (file_data *p_infile, file_data *p_outfile);
-
-/* Cached info about the .data section in the executable. */
-PIMAGE_SECTION_HEADER data_section;
-PCHAR data_start = 0;
-DWORD_PTR data_size = 0;
-
-/* Cached info about the .bss section in the executable. */
-PIMAGE_SECTION_HEADER bss_section;
-PCHAR bss_start = 0;
-DWORD_PTR bss_size = 0;
-DWORD_PTR extra_bss_size = 0;
-/* bss data that is static might be discontiguous from non-static. */
-PIMAGE_SECTION_HEADER bss_section_static;
-PCHAR bss_start_static = 0;
-DWORD_PTR bss_size_static = 0;
-DWORD_PTR extra_bss_size_static = 0;
-
-/* File handling. */
-
-/* Implementation note: this and the next functions work with ANSI
- codepage encoded file names! */
-
-int
-open_output_file (file_data *p_file, char *filename, unsigned long size)
-{
- HANDLE file;
- HANDLE file_mapping;
- void *file_base;
-
- /* We delete any existing FILENAME because loadup.el will create a
- hard link to it under the name emacs-XX.YY.ZZ.nn.exe. Evidently,
- overwriting a file on Unix breaks any hard links to it, but that
- doesn't happen on Windows. If we don't delete the file before
- creating it, all the emacs-XX.YY.ZZ.nn.exe end up being hard
- links to the same file, which defeats the purpose of these hard
- links: being able to run previous builds. */
- DeleteFileA (filename);
- file = CreateFileA (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
- if (file == INVALID_HANDLE_VALUE)
- return FALSE;
-
- file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE,
- 0, size, NULL);
- if (!file_mapping)
- return FALSE;
-
- file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size);
- if (file_base == 0)
- return FALSE;
-
- p_file->name = filename;
- p_file->size = size;
- p_file->file = file;
- p_file->file_mapping = file_mapping;
- p_file->file_base = file_base;
-
- return TRUE;
-}
-
-
-/* Routines to manipulate NT executable file sections. */
-
-/* Return pointer to section header for named section. */
-IMAGE_SECTION_HEADER *
-find_section (const char * name, IMAGE_NT_HEADERS * nt_header)
-{
- PIMAGE_SECTION_HEADER section;
- int i;
-
- section = IMAGE_FIRST_SECTION (nt_header);
-
- for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
- {
- if (strcmp ((char *)section->Name, name) == 0)
- return section;
- section++;
- }
- return NULL;
-}
-
-#if 0 /* unused */
-/* Return pointer to section header for section containing the given
- offset in its raw data area. */
-static IMAGE_SECTION_HEADER *
-offset_to_section (DWORD_PTR offset, IMAGE_NT_HEADERS * nt_header)
-{
- PIMAGE_SECTION_HEADER section;
- int i;
-
- section = IMAGE_FIRST_SECTION (nt_header);
-
- for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
- {
- if (offset >= section->PointerToRawData
- && offset < section->PointerToRawData + section->SizeOfRawData)
- return section;
- section++;
- }
- return NULL;
-}
-#endif
-
-/* Return offset to an object in dst, given offset in src. We assume
- there is at least one section in both src and dst images, and that
- the some sections may have been added to dst (after sections in src). */
-static DWORD_PTR
-relocate_offset (DWORD_PTR offset,
- IMAGE_NT_HEADERS * src_nt_header,
- IMAGE_NT_HEADERS * dst_nt_header)
-{
- PIMAGE_SECTION_HEADER src_section = IMAGE_FIRST_SECTION (src_nt_header);
- PIMAGE_SECTION_HEADER dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
- int i = 0;
-
- while (offset >= src_section->PointerToRawData)
- {
- if (offset < src_section->PointerToRawData + src_section->SizeOfRawData)
- break;
- i++;
- if (i == src_nt_header->FileHeader.NumberOfSections)
- {
- /* Handle offsets after the last section. */
- dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
- dst_section += dst_nt_header->FileHeader.NumberOfSections - 1;
- while (dst_section->PointerToRawData == 0)
- dst_section--;
- while (src_section->PointerToRawData == 0)
- src_section--;
- return offset
- + (dst_section->PointerToRawData + dst_section->SizeOfRawData)
- - (src_section->PointerToRawData + src_section->SizeOfRawData);
- }
- src_section++;
- dst_section++;
- }
- return offset +
- (dst_section->PointerToRawData - src_section->PointerToRawData);
-}
-
-#define RVA_TO_OFFSET(rva, section) \
- ((section)->PointerToRawData + ((DWORD_PTR)(rva) - (section)->VirtualAddress))
-
-#define RVA_TO_SECTION_OFFSET(rva, section) \
- ((DWORD_PTR)(rva) - (section)->VirtualAddress)
-
-/* Convert address in executing image to RVA. */
-#define PTR_TO_RVA(ptr) ((DWORD_PTR)(ptr) - (DWORD_PTR) GetModuleHandle (NULL))
-
-#define PTR_TO_OFFSET(ptr, pfile_data) \
- ((unsigned char *)(ptr) - (pfile_data)->file_base)
-
-#define OFFSET_TO_PTR(offset, pfile_data) \
- ((pfile_data)->file_base + (DWORD_PTR)(offset))
-
-#if 0 /* unused */
-#define OFFSET_TO_RVA(offset, section) \
- ((section)->VirtualAddress + ((DWORD_PTR)(offset) - (section)->PointerToRawData))
-
-#define RVA_TO_PTR(var,section,filedata) \
- ((unsigned char *)(RVA_TO_OFFSET (var,section) + (filedata).file_base))
-#endif
-
-
-/* Flip through the executable and cache the info necessary for dumping. */
-void
-get_section_info (file_data *p_infile)
-{
- PIMAGE_DOS_HEADER dos_header;
- PIMAGE_NT_HEADERS nt_header;
- int overlap;
-
- dos_header = (PIMAGE_DOS_HEADER) p_infile->file_base;
- if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
- {
- printf ("Unknown EXE header in %s...bailing.\n", p_infile->name);
- exit (1);
- }
- nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) dos_header) +
- dos_header->e_lfanew);
- if (nt_header == NULL)
- {
- printf ("Failed to find IMAGE_NT_HEADER in %s...bailing.\n",
- p_infile->name);
- exit (1);
- }
-
- /* Check the NT header signature ... */
- if (nt_header->Signature != IMAGE_NT_SIGNATURE)
- {
- printf ("Invalid IMAGE_NT_SIGNATURE 0x%lx in %s...bailing.\n",
- nt_header->Signature, p_infile->name);
- exit (1);
- }
-
- /* Locate the ".data" and ".bss" sections for Emacs. (Note that the
- actual section names are probably different from these, and might
- actually be the same section.)
-
- We do this as follows: first we determine the virtual address
- ranges in this process for the data and bss variables that we wish
- to preserve. Then we map these VAs to the section entries in the
- source image. Finally, we determine the new size of the raw data
- area for the bss section, so we can make the new image the correct
- size. */
-
- /* We arrange for the Emacs initialized data to be in a separate
- section if possible, because we cannot rely on my_begdata and
- my_edata marking out the full extent of the initialized data, at
- least on the Alpha where the linker freely reorders variables
- across libraries. If we can arrange for this, all we need to do is
- find the start and size of the EMDATA section. */
- data_section = find_section ("EMDATA", nt_header);
- if (data_section)
- {
- data_start = (char *) nt_header->OptionalHeader.ImageBase +
- data_section->VirtualAddress;
- data_size = data_section->Misc.VirtualSize;
- }
- else
- {
- /* Fallback on the old method if compiler doesn't support the
- data_set #pragma (or its equivalent). */
- data_start = my_begdata;
- data_size = my_edata - my_begdata;
- data_section = rva_to_section (PTR_TO_RVA (my_begdata), nt_header);
- if (data_section != rva_to_section (PTR_TO_RVA (my_edata), nt_header))
- {
- printf ("Initialized data is not in a single section...bailing\n");
- exit (1);
- }
- }
-
- /* As noted in lastfile.c, the Alpha (but not the Intel) MSVC linker
- globally segregates all static and public bss data (ie. across all
- linked modules, not just per module), so we must take both static
- and public bss areas into account to determine the true extent of
- the bss area used by Emacs.
-
- To be strictly correct, we dump the static and public bss areas
- used by Emacs separately if non-overlapping (since otherwise we are
- dumping bss data belonging to system libraries, eg. the static bss
- system data on the Alpha). */
-
- bss_start = my_begbss;
- bss_size = my_endbss - my_begbss;
- bss_section = rva_to_section (PTR_TO_RVA (my_begbss), nt_header);
- if (bss_section != rva_to_section (PTR_TO_RVA (my_endbss), nt_header))
- {
- printf ("Uninitialized data is not in a single section...bailing\n");
- exit (1);
- }
- /* Compute how much the .bss section's raw data will grow. */
- extra_bss_size =
- ROUND_UP (RVA_TO_SECTION_OFFSET (PTR_TO_RVA (my_endbss), bss_section),
- nt_header->OptionalHeader.FileAlignment)
- - bss_section->SizeOfRawData;
-
- bss_start_static = my_begbss_static;
- bss_size_static = my_endbss_static - my_begbss_static;
- bss_section_static = rva_to_section (PTR_TO_RVA (my_begbss_static), nt_header);
- if (bss_section_static != rva_to_section (PTR_TO_RVA (my_endbss_static), nt_header))
- {
- printf ("Uninitialized static data is not in a single section...bailing\n");
- exit (1);
- }
- /* Compute how much the static .bss section's raw data will grow. */
- extra_bss_size_static =
- ROUND_UP (RVA_TO_SECTION_OFFSET (PTR_TO_RVA (my_endbss_static), bss_section_static),
- nt_header->OptionalHeader.FileAlignment)
- - bss_section_static->SizeOfRawData;
-
- /* Combine the bss sections into one if they overlap. */
-#ifdef _ALPHA_
- overlap = 1; /* force all bss data to be dumped */
-#else
- overlap = 0;
-#endif
- if (bss_start < bss_start_static)
- {
- if (bss_start_static < bss_start + bss_size)
- overlap = 1;
- }
- else
- {
- if (bss_start < bss_start_static + bss_size_static)
- overlap = 1;
- }
- if (overlap)
- {
- if (bss_section != bss_section_static)
- {
- printf ("BSS data not in a single section...bailing\n");
- exit (1);
- }
- bss_start = min (bss_start, bss_start_static);
- bss_size = max (my_endbss, my_endbss_static) - bss_start;
- bss_section_static = 0;
- extra_bss_size = max (extra_bss_size, extra_bss_size_static);
- extra_bss_size_static = 0;
- }
-}
-
-/* Format to print a DWORD_PTR value. */
-#if defined MINGW_W64 && defined _WIN64
-# define pDWP "16llx"
-#else
-# define pDWP "08lx"
-#endif
-
-/* The dump routines. */
-
-void
-copy_executable_and_dump_data (file_data *p_infile,
- file_data *p_outfile)
-{
- unsigned char *dst, *dst_save;
- PIMAGE_DOS_HEADER dos_header;
- PIMAGE_NT_HEADERS nt_header;
- PIMAGE_NT_HEADERS dst_nt_header;
- PIMAGE_SECTION_HEADER section;
- PIMAGE_SECTION_HEADER dst_section;
- DWORD_PTR offset;
- int i;
- int be_verbose = GetEnvironmentVariable ("DEBUG_DUMP", NULL, 0) > 0;
-
-#define COPY_CHUNK(message, src, size, verbose) \
- do { \
- unsigned char *s = (void *)(src); \
- DWORD_PTR count = (size); \
- if (verbose) \
- { \
- printf ("%s\n", (message)); \
- printf ("\t0x%"pDWP" Offset in input file.\n", (DWORD_PTR)(s - p_infile->file_base)); \
- printf ("\t0x%"pDWP" Offset in output file.\n", (DWORD_PTR)(dst - p_outfile->file_base)); \
- printf ("\t0x%"pDWP" Size in bytes.\n", count); \
- } \
- memcpy (dst, s, count); \
- dst += count; \
- } while (0)
-
-#define COPY_PROC_CHUNK(message, src, size, verbose) \
- do { \
- unsigned char *s = (void *)(src); \
- DWORD_PTR count = (size); \
- if (verbose) \
- { \
- printf ("%s\n", (message)); \
- printf ("\t0x%p Address in process.\n", s); \
- printf ("\t0x%p Base output file.\n", p_outfile->file_base); \
- printf ("\t0x%"pDWP" Offset in output file.\n", (DWORD_PTR)(dst - p_outfile->file_base)); \
- printf ("\t0x%p Address in output file.\n", dst); \
- printf ("\t0x%"pDWP" Size in bytes.\n", count); \
- } \
- memcpy (dst, s, count); \
- dst += count; \
- } while (0)
-
-#define DST_TO_OFFSET() PTR_TO_OFFSET (dst, p_outfile)
-#define ROUND_UP_DST(align) \
- (dst = p_outfile->file_base + ROUND_UP (DST_TO_OFFSET (), (align)))
-#define ROUND_UP_DST_AND_ZERO(align) \
- do { \
- unsigned char *newdst = p_outfile->file_base \
- + ROUND_UP (DST_TO_OFFSET (), (align)); \
- /* Zero the alignment slop; it may actually initialize real data. */ \
- memset (dst, 0, newdst - dst); \
- dst = newdst; \
- } while (0)
-
- /* Copy the source image sequentially, ie. section by section after
- copying the headers and section table, to simplify the process of
- dumping the raw data for the bss and heap sections.
-
- Note that dst is updated implicitly by each COPY_CHUNK. */
-
- dos_header = (PIMAGE_DOS_HEADER) p_infile->file_base;
- nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) dos_header) +
- dos_header->e_lfanew);
- section = IMAGE_FIRST_SECTION (nt_header);
-
- dst = (unsigned char *) p_outfile->file_base;
-
- COPY_CHUNK ("Copying DOS header...", dos_header,
- (DWORD_PTR) nt_header - (DWORD_PTR) dos_header, be_verbose);
- dst_nt_header = (PIMAGE_NT_HEADERS) dst;
- COPY_CHUNK ("Copying NT header...", nt_header,
- (DWORD_PTR) section - (DWORD_PTR) nt_header, be_verbose);
- dst_section = (PIMAGE_SECTION_HEADER) dst;
- COPY_CHUNK ("Copying section table...", section,
- nt_header->FileHeader.NumberOfSections * sizeof (*section),
- be_verbose);
-
- /* Align the first section's raw data area, and set the header size
- field accordingly. */
- ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
- dst_nt_header->OptionalHeader.SizeOfHeaders = DST_TO_OFFSET ();
-
- for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
- {
- char msg[100];
- /* Windows section names are fixed 8-char strings, only
- zero-terminated if the name is shorter than 8 characters. */
- sprintf (msg, "Copying raw data for %.8s...", section->Name);
-
- dst_save = dst;
-
- /* Update the file-relative offset for this section's raw data (if
- it has any) in case things have been relocated; we will update
- the other offsets below once we know where everything is. */
- if (dst_section->PointerToRawData)
- dst_section->PointerToRawData = DST_TO_OFFSET ();
-
- /* Can always copy the original raw data. */
- COPY_CHUNK
- (msg, OFFSET_TO_PTR (section->PointerToRawData, p_infile),
- section->SizeOfRawData, be_verbose);
- /* Ensure alignment slop is zeroed. */
- ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
-
- /* Note that various sections below may be aliases. */
- if (section == data_section)
- {
- dst = dst_save
- + RVA_TO_SECTION_OFFSET (PTR_TO_RVA (data_start), dst_section);
- COPY_PROC_CHUNK ("Dumping initialized data...",
- data_start, data_size, be_verbose);
- dst = dst_save + dst_section->SizeOfRawData;
- }
- if (section == bss_section)
- {
- /* Dump contents of bss variables, adjusting the section's raw
- data size as necessary. */
- dst = dst_save
- + RVA_TO_SECTION_OFFSET (PTR_TO_RVA (bss_start), dst_section);
- COPY_PROC_CHUNK ("Dumping bss data...", bss_start,
- bss_size, be_verbose);
- ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment);
- dst_section->PointerToRawData = PTR_TO_OFFSET (dst_save, p_outfile);
- /* Determine new size of raw data area. */
- dst = max (dst, dst_save + dst_section->SizeOfRawData);
- dst_section->SizeOfRawData = dst - dst_save;
- dst_section->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA;
- dst_section->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA;
- }
- if (section == bss_section_static)
- {
- /* Dump contents of static bss variables, adjusting the
- section's raw data size as necessary. */
- dst = dst_save
- + RVA_TO_SECTION_OFFSET (PTR_TO_RVA (bss_start_static), dst_section);
- COPY_PROC_CHUNK ("Dumping static bss data...", bss_start_static,
- bss_size_static, be_verbose);
- ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment);
- dst_section->PointerToRawData = PTR_TO_OFFSET (dst_save, p_outfile);
- /* Determine new size of raw data area. */
- dst = max (dst, dst_save + dst_section->SizeOfRawData);
- dst_section->SizeOfRawData = dst - dst_save;
- dst_section->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA;
- dst_section->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA;
- }
-
- /* Align the section's raw data area. */
- ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment);
-
- section++;
- dst_section++;
- }
-
- /* Copy remainder of source image. */
- do
- section--;
- while (section->PointerToRawData == 0);
- offset = ROUND_UP (section->PointerToRawData + section->SizeOfRawData,
- nt_header->OptionalHeader.FileAlignment);
- COPY_CHUNK
- ("Copying remainder of executable...",
- OFFSET_TO_PTR (offset, p_infile),
- p_infile->size - offset, be_verbose);
-
- /* Final size for new image. */
- p_outfile->size = DST_TO_OFFSET ();
-
- /* Now patch up remaining file-relative offsets. */
- section = IMAGE_FIRST_SECTION (nt_header);
- dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
-
-#define ADJUST_OFFSET(var) \
- do { \
- if ((var) != 0) \
- (var) = relocate_offset ((var), nt_header, dst_nt_header); \
- } while (0)
-
- dst_nt_header->OptionalHeader.SizeOfInitializedData = 0;
- dst_nt_header->OptionalHeader.SizeOfUninitializedData = 0;
- for (i = 0; i < dst_nt_header->FileHeader.NumberOfSections; i++)
- {
- /* Recompute data sizes for completeness. */
- if (dst_section[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
- dst_nt_header->OptionalHeader.SizeOfInitializedData +=
- ROUND_UP (dst_section[i].Misc.VirtualSize, dst_nt_header->OptionalHeader.FileAlignment);
- else if (dst_section[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
- dst_nt_header->OptionalHeader.SizeOfUninitializedData +=
- ROUND_UP (dst_section[i].Misc.VirtualSize, dst_nt_header->OptionalHeader.FileAlignment);
-
- ADJUST_OFFSET (dst_section[i].PointerToLinenumbers);
- }
-
- ADJUST_OFFSET (dst_nt_header->FileHeader.PointerToSymbolTable);
-
- /* Update offsets in debug directory entries. */
- {
- IMAGE_DATA_DIRECTORY debug_dir =
- dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
- PIMAGE_DEBUG_DIRECTORY debug_entry;
-
- section = rva_to_section (debug_dir.VirtualAddress, dst_nt_header);
- if (section)
- {
- debug_entry = (PIMAGE_DEBUG_DIRECTORY)
- (RVA_TO_OFFSET (debug_dir.VirtualAddress, section) + p_outfile->file_base);
- debug_dir.Size /= sizeof (IMAGE_DEBUG_DIRECTORY);
-
- for (i = 0; i < debug_dir.Size; i++, debug_entry++)
- ADJUST_OFFSET (debug_entry->PointerToRawData);
- }
- }
-}
-
-
-/* Dump out .data and .bss sections into a new executable. */
-void
-unexec (const char *new_name, const char *old_name)
-{
- file_data in_file, out_file;
- char out_filename[MAX_PATH], in_filename[MAX_PATH], new_name_a[MAX_PATH];
- unsigned long size;
- char *p;
- char *q;
-
- /* Ignore old_name, and get our actual location from the OS. */
- if (!GetModuleFileNameA (NULL, in_filename, MAX_PATH))
- abort ();
-
- /* Can't use dostounix_filename here, since that needs its file name
- argument encoded in UTF-8. */
- for (p = in_filename; *p; p = CharNextA (p))
- if (*p == '\\')
- *p = '/';
-
- strcpy (out_filename, in_filename);
- filename_to_ansi (new_name, new_name_a);
-
- /* Change the base of the output filename to match the requested name. */
- if ((p = strrchr (out_filename, '/')) == NULL)
- abort ();
- /* The filenames have already been expanded, and will be in Unix
- format, so it is safe to expect an absolute name. */
- if ((q = strrchr (new_name_a, '/')) == NULL)
- abort ();
- strcpy (p, q);
-
-#ifdef ENABLE_CHECKING
- report_temacs_memory_usage ();
-#endif
-
- /* Make sure that the output filename has the ".exe" extension...patch
- it up if not. */
- p = out_filename + strlen (out_filename) - 4;
- if (strcmp (p, ".exe"))
- strcat (out_filename, ".exe");
-
- printf ("Dumping from %s\n", in_filename);
- printf (" to %s\n", out_filename);
-
- /* Open the undumped executable file. */
- if (!open_input_file (&in_file, in_filename))
- {
- printf ("Failed to open %s (%lu)...bailing.\n",
- in_filename, GetLastError ());
- exit (1);
- }
-
- /* Get the interesting section info, like start and size of .bss... */
- get_section_info (&in_file);
-
- /* The size of the dumped executable is the size of the original
- executable plus the size of the heap and the size of the .bss section. */
- size = in_file.size +
- extra_bss_size +
- extra_bss_size_static;
- if (!open_output_file (&out_file, out_filename, size))
- {
- printf ("Failed to open %s (%lu)...bailing.\n",
- out_filename, GetLastError ());
- exit (1);
- }
-
- copy_executable_and_dump_data (&in_file, &out_file);
-
- /* Patch up header fields; profiler is picky about this. */
- {
- PIMAGE_DOS_HEADER dos_header;
- PIMAGE_NT_HEADERS nt_header;
- HANDLE hImagehelp = LoadLibrary ("imagehlp.dll");
- DWORD headersum;
- DWORD checksum;
-
- dos_header = (PIMAGE_DOS_HEADER) out_file.file_base;
- nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew);
-
- nt_header->OptionalHeader.CheckSum = 0;
- /* nt_header->FileHeader.TimeDateStamp = time (NULL); */
- /* dos_header->e_cp = size / 512; */
- /* nt_header->OptionalHeader.SizeOfImage = size; */
-
- pfnCheckSumMappedFile = (void *) GetProcAddress (hImagehelp, "CheckSumMappedFile");
- if (pfnCheckSumMappedFile)
- {
- /* nt_header->FileHeader.TimeDateStamp = time (NULL); */
- pfnCheckSumMappedFile (out_file.file_base,
- out_file.size,
- &headersum,
- &checksum);
- nt_header->OptionalHeader.CheckSum = checksum;
- }
- FreeLibrary (hImagehelp);
- }
-
- close_file_data (&in_file);
- close_file_data (&out_file);
-}
-
-/* eof */
diff --git a/src/w32fns.c b/src/w32fns.c
index 225a3a0999e..89a4d46240a 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -11064,9 +11064,9 @@ syms_of_w32fns (void)
DEFSYM (Qjson, "json");
Fput (Qundefined_color, Qerror_conditions,
- pure_list (Qundefined_color, Qerror));
+ list (Qundefined_color, Qerror));
Fput (Qundefined_color, Qerror_message,
- build_pure_c_string ("Undefined color"));
+ build_string ("Undefined color"));
staticpro (&w32_grabbed_keys);
w32_grabbed_keys = Qnil;
diff --git a/src/w32heap.c b/src/w32heap.c
index 546a37ffd80..2ba36f01751 100644
--- a/src/w32heap.c
+++ b/src/w32heap.c
@@ -28,15 +28,6 @@
Memory allocation scheme for w32/w64:
- Buffers are mmap'ed using a very simple emulation of mmap/munmap
- - During the temacs phase, if unexec is to be used:
- * we use a private heap declared to be stored into the `dumped_data'
- * unfortunately, this heap cannot be made growable, so the size of
- blocks it can allocate is limited to (0x80000 - pagesize)
- * the blocks that are larger than this are allocated from the end
- of the `dumped_data' array; there are not so many of them.
- We use a very simple first-fit scheme to reuse those blocks.
- * we check that the private heap does not cross the area used
- by the bigger chunks.
- During the emacs phase, or always if pdumper is used:
* we create a private heap for new memory blocks
* we make sure that we never free a block that has been dumped.
@@ -95,40 +86,6 @@ typedef struct _RTL_HEAP_PARAMETERS {
SIZE_T Reserved[ 2 ];
} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS;
-/* We reserve space for dumping emacs lisp byte-code inside a static
- array. By storing it in an array, the generic mechanism in
- unexecw32.c will be able to dump it without the need to add a
- special segment to the executable. In order to be able to do this
- without losing too much space, we need to create a Windows heap at
- the specific address of the static array. The RtlCreateHeap
- available inside the NT kernel since XP will do this. It allows the
- creation of a non-growable heap at a specific address. So before
- dumping, we create a non-growable heap at the address of the
- dumped_data[] array. After dumping, we reuse memory allocated
- there without being able to free it (but most of it is not meant to
- be freed anyway), and we use a new private heap for all new
- allocations. */
-
-/* FIXME: Most of the space reserved for dumped_data[] is only used by
- the 1st bootstrap-emacs.exe built while bootstrapping. Once the
- preloaded Lisp files are byte-compiled, the next loadup uses less
- than half of the size stated below. It would be nice to find a way
- to build only the first bootstrap-emacs.exe with the large size,
- and reset that to a lower value afterwards. */
-#ifndef HAVE_UNEXEC
-/* We don't use dumped_data[], so define to a small size that won't
- matter. */
-# define DUMPED_HEAP_SIZE 10
-#else
-# if defined _WIN64 || defined WIDE_EMACS_INT
-# define DUMPED_HEAP_SIZE (28*1024*1024)
-# else
-# define DUMPED_HEAP_SIZE (24*1024*1024)
-# endif
-#endif
-
-static unsigned char dumped_data[DUMPED_HEAP_SIZE];
-
/* Info for keeping track of our dynamic heap used after dumping. */
unsigned char *data_region_base = NULL;
unsigned char *data_region_end = NULL;
@@ -213,30 +170,6 @@ heap_realloc (void *ptr, size_t size)
It would be if the memory was shared.
https://stackoverflow.com/questions/307060/what-is-the-purpose-of-allocating-pages-in-the-pagefile-with-createfilemapping */
-/* This is the function to commit memory when the heap allocator
- claims for new memory. Before dumping with unexec, we allocate
- space from the fixed size dumped_data[] array.
-*/
-static NTSTATUS NTAPI
-dumped_data_commit (PVOID Base, PVOID *CommitAddress, PSIZE_T CommitSize)
-{
- /* This is used before dumping.
-
- The private heap is stored at dumped_data[] address.
- We commit contiguous areas of the dumped_data array
- as requests arrive. */
- *CommitAddress = data_region_base + committed;
- committed += *CommitSize;
- /* Check that the private heap area does not overlap the big chunks area. */
- if (((unsigned char *)(*CommitAddress)) + *CommitSize >= bc_limit)
- {
- fprintf (stderr,
- "dumped_data_commit: memory exhausted.\nEnlarge dumped_data[]!\n");
- exit (-1);
- }
- return 0;
-}
-
/* Heap creation. */
/* We want to turn on Low Fragmentation Heap for XP and older systems.
@@ -250,99 +183,51 @@ typedef WINBASEAPI BOOL (WINAPI * HeapSetInformation_Proc)(HANDLE,HEAP_INFORMATI
#endif
void
-init_heap (bool use_dynamic_heap)
+init_heap (void)
{
- /* FIXME: Remove the condition, the 'else' branch below, and all the
- related definitions and code, including dumped_data[], when unexec
- support is removed from Emacs. */
- if (use_dynamic_heap)
- {
- /* After dumping, use a new private heap. We explicitly enable
- the low fragmentation heap (LFH) here, for the sake of pre
- Vista versions. Note: this will harmlessly fail on Vista and
- later, where the low-fragmentation heap is enabled by
- default. It will also fail on pre-Vista versions when Emacs
- is run under a debugger; set _NO_DEBUG_HEAP=1 in the
- environment before starting GDB to get low fragmentation heap
- on XP and older systems, for the price of losing "certain
- heap debug options"; for the details see
- https://msdn.microsoft.com/en-us/library/windows/desktop/aa366705%28v=vs.85%29.aspx. */
- data_region_end = data_region_base;
-
- /* Create the private heap. */
- heap = HeapCreate (0, 0, 0);
+ /* After dumping, use a new private heap. We explicitly enable
+ the low fragmentation heap (LFH) here, for the sake of pre
+ Vista versions. Note: this will harmlessly fail on Vista and
+ later, where the low-fragmentation heap is enabled by
+ default. It will also fail on pre-Vista versions when Emacs
+ is run under a debugger; set _NO_DEBUG_HEAP=1 in the
+ environment before starting GDB to get low fragmentation heap
+ on XP and older systems, for the price of losing "certain
+ heap debug options"; for the details see
+ https://msdn.microsoft.com/en-us/library/windows/desktop/aa366705%28v=vs.85%29.aspx. */
+ data_region_end = data_region_base;
+
+ /* Create the private heap. */
+ heap = HeapCreate (0, 0, 0);
#ifndef MINGW_W64
- unsigned long enable_lfh = 2;
- /* Set the low-fragmentation heap for OS before Vista. */
- HMODULE hm_kernel32dll = LoadLibrary ("kernel32.dll");
- HeapSetInformation_Proc s_pfn_Heap_Set_Information =
- (HeapSetInformation_Proc) get_proc_addr (hm_kernel32dll,
- "HeapSetInformation");
- if (s_pfn_Heap_Set_Information != NULL)
- {
- if (s_pfn_Heap_Set_Information ((PVOID) heap,
- HeapCompatibilityInformation,
- &enable_lfh, sizeof(enable_lfh)) == 0)
- DebPrint (("Enabling Low Fragmentation Heap failed: error %ld\n",
- GetLastError ()));
- }
+ unsigned long enable_lfh = 2;
+ /* Set the low-fragmentation heap for OS before Vista. */
+ HMODULE hm_kernel32dll = LoadLibrary ("kernel32.dll");
+ HeapSetInformation_Proc s_pfn_Heap_Set_Information =
+ (HeapSetInformation_Proc) get_proc_addr (hm_kernel32dll,
+ "HeapSetInformation");
+ if (s_pfn_Heap_Set_Information != NULL)
+ {
+ if (s_pfn_Heap_Set_Information ((PVOID) heap,
+ HeapCompatibilityInformation,
+ &enable_lfh, sizeof(enable_lfh)) == 0)
+ DebPrint (("Enabling Low Fragmentation Heap failed: error %ld\n",
+ GetLastError ()));
+ }
#endif
- if (os_subtype == OS_SUBTYPE_9X)
- {
- the_malloc_fn = malloc_after_dump_9x;
- the_realloc_fn = realloc_after_dump_9x;
- the_free_fn = free_after_dump_9x;
- }
- else
- {
- the_malloc_fn = malloc_after_dump;
- the_realloc_fn = realloc_after_dump;
- the_free_fn = free_after_dump;
- }
+ if (os_subtype == OS_SUBTYPE_9X)
+ {
+ the_malloc_fn = malloc_after_dump_9x;
+ the_realloc_fn = realloc_after_dump_9x;
+ the_free_fn = free_after_dump_9x;
}
- else /* Before dumping with unexec: use static heap. */
+ else
{
- /* Find the RtlCreateHeap function. Headers for this function
- are provided with the w32 DDK, but the function is available
- in ntdll.dll since XP. */
- HMODULE hm_ntdll = LoadLibrary ("ntdll.dll");
- RtlCreateHeap_Proc s_pfn_Rtl_Create_Heap
- = (RtlCreateHeap_Proc) get_proc_addr (hm_ntdll, "RtlCreateHeap");
- /* Specific parameters for the private heap. */
- RTL_HEAP_PARAMETERS params;
- ZeroMemory (&params, sizeof(params));
- params.Length = sizeof(RTL_HEAP_PARAMETERS);
-
- data_region_base = (unsigned char *)ROUND_UP (dumped_data, 0x1000);
- data_region_end = bc_limit = dumped_data + DUMPED_HEAP_SIZE;
-
- params.InitialCommit = committed = 0x1000;
- params.InitialReserve = sizeof(dumped_data);
- /* Use our own routine to commit memory from the dumped_data
- array. */
- params.CommitRoutine = &dumped_data_commit;
-
- /* Create the private heap. */
- if (s_pfn_Rtl_Create_Heap == NULL)
- {
- fprintf (stderr, "Cannot build Emacs without RtlCreateHeap being available; exiting.\n");
- exit (-1);
- }
- heap = s_pfn_Rtl_Create_Heap (0, data_region_base, 0, 0, NULL, &params);
-
- if (os_subtype == OS_SUBTYPE_9X)
- {
- fprintf (stderr, "Cannot dump Emacs on Windows 9X; exiting.\n");
- exit (-1);
- }
- else
- {
- the_malloc_fn = malloc_before_dump;
- the_realloc_fn = realloc_before_dump;
- the_free_fn = free_before_dump;
- }
+ the_malloc_fn = malloc_after_dump;
+ the_realloc_fn = realloc_after_dump;
+ the_free_fn = free_after_dump;
}
/* Update system version information to match current system. */
@@ -358,9 +243,7 @@ init_heap (bool use_dynamic_heap)
/* FREEABLE_P checks if the block can be safely freed. */
#define FREEABLE_P(addr) \
- ((DWORD_PTR)(unsigned char *)(addr) > 0 \
- && ((unsigned char *)(addr) < dumped_data \
- || (unsigned char *)(addr) >= dumped_data + DUMPED_HEAP_SIZE))
+ ((DWORD_PTR)(unsigned char *)(addr) > 0)
void *
malloc_after_dump (size_t size)
@@ -379,65 +262,6 @@ malloc_after_dump (size_t size)
return p;
}
-/* FIXME: The *_before_dump functions should be removed when pdumper
- becomes the only dumping method. */
-void *
-malloc_before_dump (size_t size)
-{
- void *p;
-
- /* Before dumping. The private heap can handle only requests for
- less than MaxBlockSize. */
- if (size < MaxBlockSize)
- {
- /* Use the private heap if possible. */
- p = heap_alloc (size);
- }
- else
- {
- /* Find the first big chunk that can hold the requested size. */
- int i = 0;
-
- for (i = 0; i < blocks_number; i++)
- {
- if (blocks[i].occupied == 0 && blocks[i].size >= size)
- break;
- }
- if (i < blocks_number)
- {
- /* If found, use it. */
- p = blocks[i].address;
- blocks[i].occupied = TRUE;
- }
- else
- {
- /* Allocate a new big chunk from the end of the dumped_data
- array. */
- if (blocks_number >= MAX_BLOCKS)
- {
- fprintf (stderr,
- "malloc_before_dump: no more big chunks available.\nEnlarge MAX_BLOCKS!\n");
- exit (-1);
- }
- bc_limit -= size;
- bc_limit = (unsigned char *)ROUND_DOWN (bc_limit, 0x10);
- p = bc_limit;
- blocks[blocks_number].address = p;
- blocks[blocks_number].size = size;
- blocks[blocks_number].occupied = TRUE;
- blocks_number++;
- /* Check that areas do not overlap. */
- if (bc_limit < dumped_data + committed)
- {
- fprintf (stderr,
- "malloc_before_dump: memory exhausted.\nEnlarge dumped_data[]!\n");
- exit (-1);
- }
- }
- }
- return p;
-}
-
/* Re-allocate the previously allocated block in ptr, making the new
block SIZE bytes long. */
void *
@@ -470,39 +294,6 @@ realloc_after_dump (void *ptr, size_t size)
return p;
}
-void *
-realloc_before_dump (void *ptr, size_t size)
-{
- void *p;
-
- /* Before dumping. */
- if (dumped_data < (unsigned char *)ptr
- && (unsigned char *)ptr < bc_limit && size <= MaxBlockSize)
- {
- p = heap_realloc (ptr, size);
- }
- else
- {
- /* In this case, either the new block is too large for the heap,
- or the old block was already too large. In both cases,
- malloc_before_dump() and free_before_dump() will take care of
- reallocation. */
- p = malloc_before_dump (size);
- /* If SIZE is below MaxBlockSize, malloc_before_dump will try to
- allocate it in the fixed heap. If that fails, we could have
- kept the block in its original place, above bc_limit, instead
- of failing the call as below. But this doesn't seem to be
- worth the added complexity, as loadup allocates only a very
- small number of large blocks, and never reallocates them. */
- if (p && ptr)
- {
- CopyMemory (p, ptr, size);
- free_before_dump (ptr);
- }
- }
- return p;
-}
-
/* Free a block allocated by `malloc', `realloc' or `calloc'. */
void
free_after_dump (void *ptr)
@@ -515,39 +306,6 @@ free_after_dump (void *ptr)
}
}
-void
-free_before_dump (void *ptr)
-{
- if (!ptr)
- return;
-
- /* Before dumping. */
- if (dumped_data < (unsigned char *)ptr
- && (unsigned char *)ptr < bc_limit)
- {
- /* Free the block if it is allocated in the private heap. */
- HeapFree (heap, 0, ptr);
- }
- else
- {
- /* Look for the big chunk. */
- int i;
-
- for (i = 0; i < blocks_number; i++)
- {
- if (blocks[i].address == ptr)
- {
- /* Reset block occupation if found. */
- blocks[i].occupied = 0;
- break;
- }
- /* What if the block is not found? We should trigger an
- error here. */
- eassert (i < blocks_number);
- }
- }
-}
-
/* On Windows 9X, HeapAlloc may return pointers that are not aligned
on 8-byte boundary, alignment which is required by the Lisp memory
management. To circumvent this problem, manually enforce alignment
@@ -617,31 +375,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..9a85bfb70c1 100644
--- a/src/w32heap.h
+++ b/src/w32heap.h
@@ -1,4 +1,4 @@
-/* Heap management routines (including unexec) for GNU Emacs on Windows NT.
+/* Heap management routines for GNU Emacs on Windows NT.
Copyright (C) 1994, 2001-2025 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -42,7 +42,7 @@ extern void report_temacs_memory_usage (void);
extern void *sbrk (ptrdiff_t size);
/* Initialize heap structures for sbrk on startup. */
-extern void init_heap (bool);
+extern void init_heap (void);
/* ----------------------------------------------------------------- */
/* Useful routines for manipulating memory-mapped files. */
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);
}
diff --git a/src/xdisp.c b/src/xdisp.c
index a801caae06f..0b8dbf514c1 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -28755,7 +28755,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
}
case 'e':
-#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
+#if !defined SYSTEM_MALLOC
{
if (NILP (Vmemory_full))
return "";
@@ -37675,7 +37675,7 @@ See also `overlay-arrow-string'. */);
DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
doc: /* String to display as an arrow in text-mode frames.
See also `overlay-arrow-position'. */);
- Voverlay_arrow_string = build_pure_c_string ("=>");
+ Voverlay_arrow_string = build_string ("=>");
DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
doc: /* List of variables (symbols) which hold markers for overlay arrows.
@@ -37808,17 +37808,17 @@ as `mode-line-format' (which see), and is used only on frames
for which no explicit name has been set \(see `modify-frame-parameters').
If the value is t, that means use `frame-title-format' for
iconified frames. */);
- /* Do not nest calls to pure_list. This works around a bug in
+ /* Do not nest calls to list. This works around a bug in
Oracle Developer Studio 12.6. */
Lisp_Object icon_title_name_format
- = pure_list (empty_unibyte_string,
- build_pure_c_string ("%b - GNU Emacs at "),
- intern_c_string ("system-name"));
+ = list (empty_unibyte_string,
+ build_string ("%b - GNU Emacs at "),
+ intern_c_string ("system-name"));
Vicon_title_format
= Vframe_title_format
- = pure_list (intern_c_string ("multiple-frames"),
- build_pure_c_string ("%b"),
- icon_title_name_format);
+ = list (intern_c_string ("multiple-frames"),
+ build_string ("%b"),
+ icon_title_name_format);
DEFVAR_LISP ("message-log-max", Vmessage_log_max,
doc: /* Maximum number of lines to keep in the message log buffer.
diff --git a/src/xfaces.c b/src/xfaces.c
index e9500b98524..fbbaffb8889 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -7537,14 +7537,14 @@ only for this purpose. */);
doc: /* Hash table of global face definitions (for internal use only.) */);
Vface_new_frame_defaults =
/* 33 entries is enough to fit all basic faces */
- make_hash_table (&hashtest_eq, 33, Weak_None, false);
+ make_hash_table (&hashtest_eq, 33, Weak_None);
DEFVAR_LISP ("face-default-stipple", Vface_default_stipple,
doc: /* Default stipple pattern used on monochrome displays.
This stipple pattern is used on monochrome displays
instead of shades of gray for a face background color.
See `set-face-stipple' for possible values for this variable. */);
- Vface_default_stipple = build_pure_c_string ("gray3");
+ Vface_default_stipple = build_string ("gray3");
DEFVAR_LISP ("tty-defined-color-alist", Vtty_defined_color_alist,
doc: /* An alist of defined terminal colors and their RGB values.
diff --git a/src/xfns.c b/src/xfns.c
index f0207ebbcee..ec7d54180e4 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -10253,9 +10253,9 @@ syms_of_xfns (void)
DEFSYM (QXdndActionPrivate, "XdndActionPrivate");
Fput (Qundefined_color, Qerror_conditions,
- pure_list (Qundefined_color, Qerror));
+ list (Qundefined_color, Qerror));
Fput (Qundefined_color, Qerror_message,
- build_pure_c_string ("Undefined color"));
+ build_string ("Undefined color"));
DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
doc: /* The shape of the pointer when over text.
@@ -10482,7 +10482,7 @@ eliminated in future versions of Emacs. */);
char gtk_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
int len = sprintf (gtk_version, "%d.%d.%d",
GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
- Vgtk_version_string = make_pure_string (gtk_version, len, len, false);
+ Vgtk_version_string = make_specified_string (gtk_version, len, len, false);
}
#endif /* USE_GTK */
@@ -10496,7 +10496,8 @@ eliminated in future versions of Emacs. */);
int len = sprintf (cairo_version, "%d.%d.%d",
CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
CAIRO_VERSION_MICRO);
- Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
+ Vcairo_version_string = make_specified_string (cairo_version, len, len,
+ false);
}
#endif
diff --git a/src/xftfont.c b/src/xftfont.c
index 459c5158d80..d18106d9936 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -810,7 +810,7 @@ do not actually have glyphs with colors that can cause Xft crashes.
The font families in this list will not be ignored when
`xft-ignore-color-fonts' is non-nil. */);
- Vxft_color_font_whitelist = list1 (build_pure_c_string ("Source Code Pro"));
+ Vxft_color_font_whitelist = list1 (build_string ("Source Code Pro"));
pdumper_do_now_and_after_load (syms_of_xftfont_for_pdumper);
}
diff --git a/src/xterm.c b/src/xterm.c
index e024b36daf5..0a877e9edf9 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -32587,7 +32587,7 @@ syms_of_xterm (void)
DEFSYM (Qwheel_right, "wheel-right");
#ifdef USE_GTK
- xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
+ xg_default_icon_file = build_string ("icons/hicolor/scalable/apps/emacs.svg");
staticpro (&xg_default_icon_file);
DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
@@ -32736,7 +32736,7 @@ If set to a non-float value, there will be no wait at all. */);
DEFVAR_LISP ("x-keysym-table", Vx_keysym_table,
doc: /* Hash table of character codes indexed by X keysym codes. */);
- Vx_keysym_table = make_hash_table (&hashtest_eql, 900, Weak_None, false);
+ Vx_keysym_table = make_hash_table (&hashtest_eql, 900, Weak_None);
DEFVAR_BOOL ("x-frame-normalize-before-maximize",
x_frame_normalize_before_maximize,