emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/native-comp 9aa5203: Fix loading *.eln files when Emacs is insta


From: Eli Zaretskii
Subject: feature/native-comp 9aa5203: Fix loading *.eln files when Emacs is installed via symlinks
Date: Sat, 17 Apr 2021 09:50:49 -0400 (EDT)

branch: feature/native-comp
commit 9aa5203b542f0c9ea7d074c6cfde2a28b466f5d1
Author: Eli Zaretskii <eliz@gnu.org>
Commit: Eli Zaretskii <eliz@gnu.org>

    Fix loading *.eln files when Emacs is installed via symlinks
    
    * src/emacs.c (real_filename, set_invocation_vars)
    (init_vars_for_load): Functions deleted; callers adjusted.
    (init_cmdargs): Put back all the code which was extracted into
    set_invocation_vars.
    (load_pdump_find_executable): Make sure the return value has any
    symlinks in it expanded.
    (load_pdump): Accept only 2 arguments, not 3.  Determine both the
    file name of the Emacs executable and of the dump file in
    synchronized manner, so that if we decided to look for the dump
    file in its hardcoded installation directory, the directory of the
    Emacs executable will also be where we expect it to be installed.
    Pass only 2 arguments to pdumper_load.  (Bug#47800)  (Bug#44128)
    * src/pdumper.c (dump_do_dump_relocation): Use emacs_execdir
    instead of Vinvocation_directory to produce absolute file names of
    *.eln files that are recorded in the pdumper file.  Pass the full
    .eln file name to fixup_eln_load_path.
    (pdumper_set_emacs_execdir) [HAVE_NATIVE_COMP]: New function.
    (pdumper_load) [HAVE_NATIVE_COMP]: Call pdumper_set_emacs_execdir.
    * src/comp.c (fixup_eln_load_path): Use Fsubstring_no_properties
    instead of Fsubstring.  No need to cons a file name, as the caller
    already did that.  Use explicit const string to avoid "magic"
    values.
    
    * lisp/startup.el (normal-top-level): Use expand-file-name instead
    of concat.  Decode comp-eln-load-path and expand-file-name its
    members.
---
 lisp/startup.el |  13 +++-
 src/comp.c      |  35 ++++-----
 src/comp.h      |   6 +-
 src/emacs.c     | 223 +++++++++++++++++++++++---------------------------------
 src/lisp.h      |   1 -
 src/pdumper.c   |  93 +++++++++++++++++------
 src/pdumper.h   |   3 +-
 7 files changed, 200 insertions(+), 174 deletions(-)

diff --git a/lisp/startup.el b/lisp/startup.el
index 6e0faf3..01d2814 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -544,7 +544,8 @@ It is the default value of the variable `top-level'."
           (dolist (path (split-string path-env path-separator))
             (unless (string= "" path)
               (push path comp-eln-load-path)))))
-      (push (concat user-emacs-directory "eln-cache/") comp-eln-load-path)
+      (push (expand-file-name "eln-cache/" user-emacs-directory)
+            comp-eln-load-path)
       ;; When $HOME is set to '/nonexistent' means we are running the
       ;; testsuite, add a temporary folder in front to produce there
       ;; new compilations.
@@ -636,6 +637,16 @@ It is the default value of the variable `top-level'."
                (set pathsym (mapcar (lambda (dir)
                                       (decode-coding-string dir coding t))
                                     path)))))
+        (when (featurep 'nativecomp)
+          (let ((npath (symbol-value 'comp-eln-load-path)))
+            (set 'comp-eln-load-path
+                 (mapcar (lambda (dir)
+                           ;; Call expand-file-name to remove all the
+                           ;; pesky ".." from the directyory names in
+                           ;; comp-eln-load-path.
+                           (expand-file-name
+                            (decode-coding-string dir coding t)))
+                         npath))))
        (dolist (filesym '(data-directory doc-directory exec-directory
                                          installation-directory
                                          invocation-directory invocation-name
diff --git a/src/comp.c b/src/comp.c
index c4b9b4b..5094731 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -4749,29 +4749,30 @@ maybe_defer_native_compilation (Lisp_Object 
function_name,
 /* Functions used to load eln files.  */
 /**************************************/
 
-/* Fixup the system eln-cache dir.  This is the last entry in
-   `comp-eln-load-path'.  */
+/* Fixup the system eln-cache directory, which is the last entry in
+   `comp-eln-load-path'.  Argument is a .eln file in that directory.  */
 void
 fixup_eln_load_path (Lisp_Object eln_filename)
 {
   Lisp_Object last_cell = Qnil;
-  Lisp_Object tmp = Vcomp_eln_load_path;
-  FOR_EACH_TAIL (tmp)
-    if (CONSP (tmp))
-      last_cell = tmp;
-
-  Lisp_Object eln_cache_sys =
-    Ffile_name_directory (concat2 (Vinvocation_directory,
-                                  eln_filename));
-  bool preloaded =
-    !NILP (Fequal (Fsubstring (eln_cache_sys, make_fixnum (-10),
-                              make_fixnum (-1)),
-                  build_string ("preloaded")));
+  Lisp_Object tem = Vcomp_eln_load_path;
+  FOR_EACH_TAIL (tem)
+    if (CONSP (tem))
+      last_cell = tem;
+
+  const char preloaded[] = "preloaded";
+  ptrdiff_t preloaded_len = sizeof (preloaded) - 1;
+  Lisp_Object eln_cache_sys = Ffile_name_directory (eln_filename);
+  bool preloaded_p =
+    !NILP (Fequal (Fsubstring_no_properties (eln_cache_sys,
+                                            make_fixnum (-preloaded_len - 1),
+                                            make_fixnum (-1)),
+                  build_string (preloaded)));
   /* One or two directories up...  */
-  for (int i = 0; i < (preloaded ? 2 : 1); i++)
+  for (int i = 0; i < (preloaded_p ? 2 : 1); i++)
     eln_cache_sys =
-      Ffile_name_directory (Fsubstring (eln_cache_sys, Qnil,
-                                       make_fixnum (-1)));
+      Ffile_name_directory (Fsubstring_no_properties (eln_cache_sys, Qnil,
+                                                     make_fixnum (-1)));
   Fsetcar (last_cell, eln_cache_sys);
 }
 
diff --git a/src/comp.h b/src/comp.h
index e17b843..03d22df 100644
--- a/src/comp.h
+++ b/src/comp.h
@@ -34,7 +34,11 @@ enum {
 struct Lisp_Native_Comp_Unit
 {
   union vectorlike_header header;
-  /* Original eln file loaded. */
+  /* The original eln file loaded.  In the pdumper file this is stored
+     as a cons cell of 2 alternative file names: the car is the
+     filename relative to the directory of an installed binary, the
+     cdr is the filename relative to the directory of an uninstalled
+     binary.  This is arranged in loadup.el.  */
   Lisp_Object file;
   Lisp_Object optimize_qualities;
   /* Guard anonymous lambdas against Garbage Collection and serve
diff --git a/src/emacs.c b/src/emacs.c
index a256564..d27b1c1 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -440,53 +440,33 @@ terminate_due_to_signal (int sig, int backtrace_limit)
   exit (1);
 }
 
-/* Return the real filename following symlinks in case.
-   The caller should deallocate the returned buffer.  */
-
-static char *
-real_filename (char *filename)
-{
-  char *real_name;
-#ifdef WINDOWSNT
-  /* w32_my_exename resolves symlinks internally, so no need to
-     call realpath.  */
-  real_name = xstrdup (filename);
-#else
-  real_name = realpath (filename, NULL);
-  if (!real_name)
-    fatal ("could not resolve realpath of \"%s\": %s",
-          filename, strerror (errno));
-#endif
-  return real_name;
-}
-
-/* Set `invocation-name' `invocation-directory'.  */
-
+
+/* Code for dealing with Lisp access to the Unix command line.  */
 static void
-set_invocation_vars (char *argv0, char const *original_pwd)
+init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd)
 {
-  Lisp_Object raw_name, handler;
+  int i;
+  Lisp_Object name, dir, handler;
+  ptrdiff_t count = SPECPDL_INDEX ();
+  Lisp_Object raw_name;
   AUTO_STRING (slash_colon, "/:");
 
+  initial_argv = argv;
+  initial_argc = argc;
+
 #ifdef WINDOWSNT
-  /* Must use argv0 converted to UTF-8, as it begets many standard
+  /* Must use argv[0] converted to UTF-8, as it begets many standard
      file and directory names.  */
   {
-    char argv0_1[MAX_UTF8_PATH];
+    char argv0[MAX_UTF8_PATH];
 
-    /* Avoid calling 'openp' below, as we aren't ready for that yet:
-       emacs_dir is not yet defined in the environment, and therefore
-       emacs_root_dir, called by expand-file-name, will abort.  */
-    if (!IS_ABSOLUTE_FILE_NAME (argv0))
-      argv0 = w32_my_exename ();
-
-    if (filename_from_ansi (argv0, argv0_1) == 0)
-      raw_name = build_unibyte_string (argv0_1);
-    else
+    if (filename_from_ansi (argv[0], argv0) == 0)
       raw_name = build_unibyte_string (argv0);
+    else
+      raw_name = build_unibyte_string (argv[0]);
   }
 #else
-  raw_name = build_unibyte_string (argv0);
+  raw_name = build_unibyte_string (argv[0]);
 #endif
 
   /* Add /: to the front of the name
@@ -495,26 +475,16 @@ set_invocation_vars (char *argv0, char const 
*original_pwd)
   if (! NILP (handler))
     raw_name = concat2 (slash_colon, raw_name);
 
-  char *filename = real_filename (SSDATA (raw_name));
-  raw_name = build_unibyte_string (filename);
-  xfree (filename);
-
   Vinvocation_name = Ffile_name_nondirectory (raw_name);
   Vinvocation_directory = Ffile_name_directory (raw_name);
 
-#ifdef WINDOWSNT
-  eassert (!NILP (Vinvocation_directory)
-          && !NILP (Ffile_name_absolute_p (Vinvocation_directory)));
-#endif
-
-  /* If we got no directory in argv0, search PATH to find where
+  /* If we got no directory in argv[0], search PATH to find where
      Emacs actually came from.  */
   if (NILP (Vinvocation_directory))
     {
       Lisp_Object found;
-      int yes =
-       openp (Vexec_path, Vinvocation_name, Vexec_suffixes, &found,
-              make_fixnum (X_OK), false, false);
+      int yes = openp (Vexec_path, Vinvocation_name, Vexec_suffixes,
+                      &found, make_fixnum (X_OK), false, false);
       if (yes == 1)
        {
          /* Add /: to the front of the name
@@ -536,38 +506,6 @@ set_invocation_vars (char *argv0, char const *original_pwd)
 
       Vinvocation_directory = Fexpand_file_name (Vinvocation_directory, odir);
     }
-}
-
-/* Initialize a number of variables (ultimately
-   'Vinvocation_directory') needed by pdumper to complete native code
-   load.  */
-
-void
-init_vars_for_load (char *argv0, char const *original_pwd)
-{
-  /* This function is called from within pdumper while loading (as
-     soon as we are able to allocate) or later during boot if pdumper
-     is not used.  No need to run it twice.  */
-  static bool double_run_guard;
-  if (double_run_guard)
-    return;
-  double_run_guard = true;
-
-  init_callproc_1 ();  /* Must precede init_cmdargs and init_sys_modes.  */
-  set_invocation_vars (argv0, original_pwd);
-}
-
-
-/* Code for dealing with Lisp access to the Unix command line.  */
-static void
-init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd)
-{
-  int i;
-  Lisp_Object name, dir;
-  ptrdiff_t count = SPECPDL_INDEX ();
-
-  initial_argv = argv;
-  initial_argc = argc;
 
   Vinstallation_directory = Qnil;
 
@@ -801,6 +739,8 @@ load_pdump_find_executable (char const *argv0, ptrdiff_t 
*candidate_size)
      implementation of malloc, since the caller calls our free.  */
 #ifdef WINDOWSNT
   char *prog_fname = w32_my_exename ();
+  if (prog_fname)
+    *candidate_size = strlen (prog_fname) + 1;
   return prog_fname ? xstrdup (prog_fname) : NULL;
 #else  /* !WINDOWSNT */
   char *candidate = NULL;
@@ -846,7 +786,19 @@ load_pdump_find_executable (char const *argv0, ptrdiff_t 
*candidate_size)
       struct stat st;
       if (file_access_p (candidate, X_OK)
          && stat (candidate, &st) == 0 && S_ISREG (st.st_mode))
-       return candidate;
+       {
+         /* People put on PATH a symlink to the real Emacs
+            executable, with all the auxiliary files where the real
+            executable lives.  Support that.  */
+         if (lstat (candidate, &st) == 0 && S_ISLNK (st.st_mode))
+           {
+             char *real_name = realpath (candidate, NULL);
+
+             if (real_name)
+               return real_name;
+           }
+         return candidate;
+       }
       *candidate = '\0';
     }
   while (*path++ != '\0');
@@ -856,10 +808,11 @@ load_pdump_find_executable (char const *argv0, ptrdiff_t 
*candidate_size)
 }
 
 static void
-load_pdump (int argc, char **argv, char const *original_pwd)
+load_pdump (int argc, char **argv)
 {
   const char *const suffix = ".pdmp";
   int result;
+  char *emacs_executable = argv[0];
   const char *strip_suffix =
 #if defined DOS_NT || defined CYGWIN
     ".exe"
@@ -889,9 +842,19 @@ load_pdump (int argc, char **argv, char const 
*original_pwd)
       skip_args++;
     }
 
+  /* Where's our executable?  */
+  ptrdiff_t bufsize, exec_bufsize;
+  emacs_executable = load_pdump_find_executable (argv[0], &bufsize);
+  exec_bufsize = bufsize;
+
+  /* If we couldn't find our executable, go straight to looking for
+     the dump in the hardcoded location.  */
+  if (!(emacs_executable && *emacs_executable))
+    goto hardcoded;
+
   if (dump_file)
     {
-      result = pdumper_load (dump_file, argv[0], original_pwd);
+      result = pdumper_load (dump_file, emacs_executable);
 
       if (result != PDUMPER_LOAD_SUCCESS)
         fatal ("could not load dump file \"%s\": %s",
@@ -905,42 +868,29 @@ load_pdump (int argc, char **argv, char const 
*original_pwd)
      so we can't use decode_env_path.  We're working in whatever
      encoding the system natively uses for filesystem access, so
      there's no need for character set conversion.  */
-  ptrdiff_t bufsize;
-  dump_file = load_pdump_find_executable (argv[0], &bufsize);
-
-  /* If we couldn't find our executable, go straight to looking for
-     the dump in the hardcoded location.  */
-  if (dump_file && *dump_file)
-    {
-      char *real_exename = real_filename (dump_file);
-      xfree (dump_file);
-      dump_file = real_exename;
-      ptrdiff_t exenamelen = strlen (dump_file);
-#ifndef WINDOWSNT
-      bufsize = exenamelen + 1;
-#endif
-      if (strip_suffix)
-        {
-         ptrdiff_t strip_suffix_length = strlen (strip_suffix);
-         ptrdiff_t prefix_length = exenamelen - strip_suffix_length;
-         if (0 <= prefix_length
-             && !memcmp (&dump_file[prefix_length], strip_suffix,
-                         strip_suffix_length))
-           exenamelen = prefix_length;
-        }
-      ptrdiff_t needed = exenamelen + strlen (suffix) + 1;
-      if (bufsize < needed)
-       dump_file = xpalloc (dump_file, &bufsize, needed - bufsize, -1, 1);
-      strcpy (dump_file + exenamelen, suffix);
-      result = pdumper_load (dump_file, argv[0], original_pwd);
-      if (result == PDUMPER_LOAD_SUCCESS)
-        goto out;
-
-      if (result != PDUMPER_LOAD_FILE_NOT_FOUND)
-        fatal ("could not load dump file \"%s\": %s",
-               dump_file, dump_error_to_string (result));
-    }
-
+  ptrdiff_t exenamelen = strlen (emacs_executable);
+  if (strip_suffix)
+    {
+      ptrdiff_t strip_suffix_length = strlen (strip_suffix);
+      ptrdiff_t prefix_length = exenamelen - strip_suffix_length;
+      if (0 <= prefix_length
+         && !memcmp (&emacs_executable[prefix_length], strip_suffix,
+                     strip_suffix_length))
+       exenamelen = prefix_length;
+    }
+  ptrdiff_t needed = exenamelen + strlen (suffix) + 1;
+  dump_file = xpalloc (NULL, &bufsize, needed - bufsize, -1, 1);
+  memcpy (dump_file, emacs_executable, exenamelen);
+  strcpy (dump_file + exenamelen, suffix);
+  result = pdumper_load (dump_file, emacs_executable);
+  if (result == PDUMPER_LOAD_SUCCESS)
+    goto out;
+
+  if (result != PDUMPER_LOAD_FILE_NOT_FOUND)
+    fatal ("could not load dump file \"%s\": %s",
+          dump_file, dump_error_to_string (result));
+
+ hardcoded:
 #ifdef WINDOWSNT
   /* On MS-Windows, PATH_EXEC normally starts with a literal
      "%emacs_dir%", so it will never work without some tweaking.  */
@@ -951,11 +901,11 @@ load_pdump (int argc, char **argv, char const 
*original_pwd)
      "emacs.pdmp" so that the Emacs binary still works if the user
      copies and renames it.  */
   const char *argv0_base = "emacs";
-  ptrdiff_t needed = (strlen (path_exec)
-                      + 1
-                      + strlen (argv0_base)
-                      + strlen (suffix)
-                      + 1);
+  needed = (strlen (path_exec)
+           + 1
+           + strlen (argv0_base)
+           + strlen (suffix)
+           + 1);
   if (bufsize < needed)
     {
       xfree (dump_file);
@@ -963,7 +913,19 @@ load_pdump (int argc, char **argv, char const 
*original_pwd)
     }
   sprintf (dump_file, "%s%c%s%s",
            path_exec, DIRECTORY_SEP, argv0_base, suffix);
-  result = pdumper_load (dump_file, argv[0], original_pwd);
+  /* Assume the Emacs binary lives in a sibling directory as set up by
+     the default installation configuration.  */
+  const char *go_up = "../../../../bin/";
+  needed += strlen (strip_suffix) - strlen (suffix) + strlen (go_up);
+  if (exec_bufsize < needed)
+    {
+      xfree (emacs_executable);
+      emacs_executable = xpalloc (NULL, &exec_bufsize, needed - exec_bufsize,
+                                 -1, 1);
+    }
+  sprintf (emacs_executable, "%s%c%s%s%s",
+          path_exec, DIRECTORY_SEP, go_up, argv0_base, strip_suffix);
+  result = pdumper_load (dump_file, emacs_executable);
 
   if (result == PDUMPER_LOAD_FILE_NOT_FOUND)
     {
@@ -998,7 +960,7 @@ load_pdump (int argc, char **argv, char const *original_pwd)
 #endif
       sprintf (dump_file, "%s%c%s%s",
               path_exec, DIRECTORY_SEP, argv0_base, suffix);
-      result = pdumper_load (dump_file, argv[0], original_pwd);
+      result = pdumper_load (dump_file, emacs_executable);
     }
 
   if (result != PDUMPER_LOAD_SUCCESS)
@@ -1010,6 +972,7 @@ load_pdump (int argc, char **argv, char const 
*original_pwd)
 
  out:
   xfree (dump_file);
+  xfree (emacs_executable);
 }
 #endif /* HAVE_PDUMPER */
 
@@ -1320,10 +1283,9 @@ main (int argc, char **argv)
   w32_init_main_thread ();
 #endif
 
-  emacs_wd = emacs_get_current_dir_name ();
 #ifdef HAVE_PDUMPER
   if (attempt_load_pdump)
-    load_pdump (argc, argv, emacs_wd);
+    load_pdump (argc, argv);
 #endif
 
   argc = maybe_disable_address_randomization (argc, argv);
@@ -1395,6 +1357,7 @@ main (int argc, char **argv)
       exit (0);
     }
 
+  emacs_wd = emacs_get_current_dir_name ();
 #ifdef HAVE_PDUMPER
   if (dumped_with_pdumper_p ())
     pdumper_record_wd (emacs_wd);
@@ -2038,8 +2001,6 @@ Using an Emacs configured with --with-x-toolkit=lucid 
does not have this problem
   /* Init buffer storage and default directory of main buffer.  */
   init_buffer ();
 
-  init_vars_for_load (argv[0], original_pwd);
-
   /* Must precede init_lread.  */
   init_cmdargs (argc, argv, skip_args, original_pwd);
 
diff --git a/src/lisp.h b/src/lisp.h
index 474e49c..f83c55f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4450,7 +4450,6 @@ extern bool display_arg;
 extern Lisp_Object decode_env_path (const char *, const char *, bool);
 extern Lisp_Object empty_unibyte_string, empty_multibyte_string;
 extern AVOID terminate_due_to_signal (int, int);
-extern void init_vars_for_load (char *, char const *);
 #ifdef WINDOWSNT
 extern Lisp_Object Vlibrary_cache;
 #endif
diff --git a/src/pdumper.c b/src/pdumper.c
index dc893c5..c9285dd 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -4356,6 +4356,16 @@ pdumper_remember_lv_ptr_raw_impl (void *ptr, enum 
Lisp_Type type)
 }
 
 
+#ifdef HAVE_NATIVE_COMP
+/* This records the directory where the Emacs executable lives, to be
+   used for locating the native-lisp directory from which we need to
+   load the preloaded *.eln files.  See pdumper_set_emacs_execdir
+   below.  */
+static char *emacs_execdir;
+static ptrdiff_t execdir_size;
+static ptrdiff_t execdir_len;
+#endif
+
 /* Dump runtime */
 enum dump_memory_protection
 {
@@ -5269,35 +5279,54 @@ dump_do_dump_relocation (const uintptr_t dump_base,
        struct Lisp_Native_Comp_Unit *comp_u =
          dump_ptr (dump_base, reloc_offset);
        comp_u->lambda_gc_guard_h = CALLN (Fmake_hash_table, QCtest, Qeq);
-       if (!CONSP (comp_u->file))
+       if (STRINGP (comp_u->file))
          error ("Trying to load incoherent dumped eln file %s",
                 SSDATA (comp_u->file));
 
+       /* emacs_execdir is always unibyte, but the file names in
+          comp_u->file could be multibyte, so we need to encode
+          them.  */
+       Lisp_Object cu_file1 = ENCODE_FILE (XCAR (comp_u->file));
+       Lisp_Object cu_file2 = ENCODE_FILE (XCDR (comp_u->file));
+       ptrdiff_t fn1_len = SBYTES (cu_file1), fn2_len = SBYTES (cu_file2);
+       Lisp_Object eln_fname;
+       char *fndata;
+
        /* Check just once if this is a local build or Emacs was installed.  */
+       /* Can't use expand-file-name here, because we are too early
+          in the startup, and we will crash at least on WINDOWSNT.  */
        if (installation_state == UNKNOWN)
          {
-           /* Can't use expand-file-name here, because we are too
-              early in the startup, and we will crash at least on
-              WINDOWSNT.  */
-           Lisp_Object fname =
-             concat2 (Vinvocation_directory, XCAR (comp_u->file));
-           if (file_access_p (SSDATA (ENCODE_FILE (fname)), F_OK))
-             {
-               installation_state = INSTALLED;
-               fixup_eln_load_path (XCAR (comp_u->file));
-             }
+           eln_fname = make_uninit_string (execdir_len + fn1_len);
+           fndata = SSDATA (eln_fname);
+           memcpy (fndata, emacs_execdir, execdir_len);
+           memcpy (fndata + execdir_len, SSDATA (cu_file1), fn1_len);
+           if (file_access_p (fndata, F_OK))
+             installation_state = INSTALLED;
            else
              {
+               eln_fname = make_uninit_string (execdir_len + fn2_len);
+               fndata = SSDATA (eln_fname);
+               memcpy (fndata, emacs_execdir, execdir_len);
+               memcpy (fndata + execdir_len, SSDATA (cu_file2), fn2_len);
                installation_state = LOCAL_BUILD;
-               fixup_eln_load_path (XCDR (comp_u->file));
              }
+           fixup_eln_load_path (eln_fname);
+         }
+       else
+         {
+           ptrdiff_t fn_len =
+             installation_state == INSTALLED ? fn1_len : fn2_len;
+           Lisp_Object cu_file =
+             installation_state == INSTALLED ? cu_file1 : cu_file2;
+           eln_fname = make_uninit_string (execdir_len + fn_len);
+           fndata = SSDATA (eln_fname);
+           memcpy (fndata, emacs_execdir, execdir_len);
+           memcpy (fndata + execdir_len, SSDATA (cu_file), fn_len);
          }
 
-       comp_u->file =
-         concat2 (Vinvocation_directory,
-                  installation_state == INSTALLED
-                  ? XCAR (comp_u->file) : XCDR (comp_u->file));
-       comp_u->handle = dynlib_open (SSDATA (ENCODE_FILE (comp_u->file)));
+       comp_u->file = eln_fname;
+       comp_u->handle = dynlib_open (SSDATA (eln_fname));
        if (!comp_u->handle)
          error ("%s", dynlib_error ());
        load_comp_unit (comp_u, true, false);
@@ -5435,6 +5464,26 @@ dump_do_all_emacs_relocations (const struct dump_header 
*const header,
     dump_do_emacs_relocation (dump_base, r[i]);
 }
 
+#ifdef HAVE_NATIVE_COMP
+/* Compute and record the directory of the Emacs executable given the
+   file name of that executable.  */
+static void
+pdumper_set_emacs_execdir (char *emacs_executable)
+{
+  char *p = emacs_executable + strlen (emacs_executable);
+
+  while (p > emacs_executable
+        && !IS_DIRECTORY_SEP (p[-1]))
+    --p;
+  eassert (p > emacs_executable);
+  emacs_execdir = xpalloc (emacs_execdir, &execdir_size,
+                          p - emacs_executable + 1 - execdir_size, -1, 1);
+  memcpy (emacs_execdir, emacs_executable, p - emacs_executable);
+  execdir_len = p - emacs_executable;
+  emacs_execdir[execdir_len] = '\0';
+}
+#endif
+
 enum dump_section
   {
    DS_HOT,
@@ -5451,7 +5500,7 @@ static Lisp_Object *pdumper_hashes = &zero_vector;
    N.B. We run very early in initialization, so we can't use lisp,
    unwinding, xmalloc, and so on.  */
 int
-pdumper_load (const char *dump_filename, char *argv0, char const *original_pwd)
+pdumper_load (const char *dump_filename, char *argv0)
 {
   intptr_t dump_size;
   struct stat stat;
@@ -5607,9 +5656,11 @@ pdumper_load (const char *dump_filename, char *argv0, 
char const *original_pwd)
   for (int i = 0; i < nr_dump_hooks; ++i)
     dump_hooks[i] ();
 
-  /* Once we can allocate and before loading .eln files we must set
-     Vinvocation_directory (.eln paths are relative to it). */
-  init_vars_for_load (argv0, original_pwd);
+#ifdef HAVE_NATIVE_COMP
+  pdumper_set_emacs_execdir (argv0);
+#else
+  (void) argv0;
+#endif
 
   dump_do_all_dump_reloc_for_phase (header, dump_base, LATE_RELOCS);
   dump_do_all_dump_reloc_for_phase (header, dump_base, VERY_LATE_RELOCS);
diff --git a/src/pdumper.h b/src/pdumper.h
index 49e6739..deec9af 100644
--- a/src/pdumper.h
+++ b/src/pdumper.h
@@ -140,8 +140,7 @@ enum pdumper_load_result
     PDUMPER_LOAD_ERROR /* Must be last, as errno may be added.  */
   };
 
-int pdumper_load (const char *dump_filename, char *argv0,
-                 char const *original_pwd);
+int pdumper_load (const char *dump_filename, char *argv0);
 
 struct pdumper_loaded_dump
 {



reply via email to

[Prev in Thread] Current Thread [Next in Thread]