aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2021-04-17 16:49:16 +0300
committerEli Zaretskii2021-04-17 16:49:16 +0300
commit9aa5203b542f0c9ea7d074c6cfde2a28b466f5d1 (patch)
tree0eb9faeeb7b1881aafca2795036e1989dae9d35d /src
parentf9c1008ced59f003d48dd7be39e9ec4aa0f02484 (diff)
downloademacs-9aa5203b542f0c9ea7d074c6cfde2a28b466f5d1.tar.gz
emacs-9aa5203b542f0c9ea7d074c6cfde2a28b466f5d1.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/comp.c35
-rw-r--r--src/comp.h6
-rw-r--r--src/emacs.c223
-rw-r--r--src/lisp.h1
-rw-r--r--src/pdumper.c93
-rw-r--r--src/pdumper.h3
6 files changed, 188 insertions, 173 deletions
diff --git a/src/comp.c b/src/comp.c
index c4b9b4b6c10..50947316df8 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -4749,29 +4749,30 @@ maybe_defer_native_compilation (Lisp_Object function_name,
4749/* Functions used to load eln files. */ 4749/* Functions used to load eln files. */
4750/**************************************/ 4750/**************************************/
4751 4751
4752/* Fixup the system eln-cache dir. This is the last entry in 4752/* Fixup the system eln-cache directory, which is the last entry in
4753 `comp-eln-load-path'. */ 4753 `comp-eln-load-path'. Argument is a .eln file in that directory. */
4754void 4754void
4755fixup_eln_load_path (Lisp_Object eln_filename) 4755fixup_eln_load_path (Lisp_Object eln_filename)
4756{ 4756{
4757 Lisp_Object last_cell = Qnil; 4757 Lisp_Object last_cell = Qnil;
4758 Lisp_Object tmp = Vcomp_eln_load_path; 4758 Lisp_Object tem = Vcomp_eln_load_path;
4759 FOR_EACH_TAIL (tmp) 4759 FOR_EACH_TAIL (tem)
4760 if (CONSP (tmp)) 4760 if (CONSP (tem))
4761 last_cell = tmp; 4761 last_cell = tem;
4762 4762
4763 Lisp_Object eln_cache_sys = 4763 const char preloaded[] = "preloaded";
4764 Ffile_name_directory (concat2 (Vinvocation_directory, 4764 ptrdiff_t preloaded_len = sizeof (preloaded) - 1;
4765 eln_filename)); 4765 Lisp_Object eln_cache_sys = Ffile_name_directory (eln_filename);
4766 bool preloaded = 4766 bool preloaded_p =
4767 !NILP (Fequal (Fsubstring (eln_cache_sys, make_fixnum (-10), 4767 !NILP (Fequal (Fsubstring_no_properties (eln_cache_sys,
4768 make_fixnum (-1)), 4768 make_fixnum (-preloaded_len - 1),
4769 build_string ("preloaded"))); 4769 make_fixnum (-1)),
4770 build_string (preloaded)));
4770 /* One or two directories up... */ 4771 /* One or two directories up... */
4771 for (int i = 0; i < (preloaded ? 2 : 1); i++) 4772 for (int i = 0; i < (preloaded_p ? 2 : 1); i++)
4772 eln_cache_sys = 4773 eln_cache_sys =
4773 Ffile_name_directory (Fsubstring (eln_cache_sys, Qnil, 4774 Ffile_name_directory (Fsubstring_no_properties (eln_cache_sys, Qnil,
4774 make_fixnum (-1))); 4775 make_fixnum (-1)));
4775 Fsetcar (last_cell, eln_cache_sys); 4776 Fsetcar (last_cell, eln_cache_sys);
4776} 4777}
4777 4778
diff --git a/src/comp.h b/src/comp.h
index e17b843d139..03d22dfaa0e 100644
--- a/src/comp.h
+++ b/src/comp.h
@@ -34,7 +34,11 @@ enum {
34struct Lisp_Native_Comp_Unit 34struct Lisp_Native_Comp_Unit
35{ 35{
36 union vectorlike_header header; 36 union vectorlike_header header;
37 /* Original eln file loaded. */ 37 /* The original eln file loaded. In the pdumper file this is stored
38 as a cons cell of 2 alternative file names: the car is the
39 filename relative to the directory of an installed binary, the
40 cdr is the filename relative to the directory of an uninstalled
41 binary. This is arranged in loadup.el. */
38 Lisp_Object file; 42 Lisp_Object file;
39 Lisp_Object optimize_qualities; 43 Lisp_Object optimize_qualities;
40 /* Guard anonymous lambdas against Garbage Collection and serve 44 /* Guard anonymous lambdas against Garbage Collection and serve
diff --git a/src/emacs.c b/src/emacs.c
index a2565645c6c..d27b1c1351d 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -440,53 +440,33 @@ terminate_due_to_signal (int sig, int backtrace_limit)
440 exit (1); 440 exit (1);
441} 441}
442 442
443/* Return the real filename following symlinks in case. 443
444 The caller should deallocate the returned buffer. */ 444/* Code for dealing with Lisp access to the Unix command line. */
445
446static char *
447real_filename (char *filename)
448{
449 char *real_name;
450#ifdef WINDOWSNT
451 /* w32_my_exename resolves symlinks internally, so no need to
452 call realpath. */
453 real_name = xstrdup (filename);
454#else
455 real_name = realpath (filename, NULL);
456 if (!real_name)
457 fatal ("could not resolve realpath of \"%s\": %s",
458 filename, strerror (errno));
459#endif
460 return real_name;
461}
462
463/* Set `invocation-name' `invocation-directory'. */
464
465static void 445static void
466set_invocation_vars (char *argv0, char const *original_pwd) 446init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd)
467{ 447{
468 Lisp_Object raw_name, handler; 448 int i;
449 Lisp_Object name, dir, handler;
450 ptrdiff_t count = SPECPDL_INDEX ();
451 Lisp_Object raw_name;
469 AUTO_STRING (slash_colon, "/:"); 452 AUTO_STRING (slash_colon, "/:");
470 453
454 initial_argv = argv;
455 initial_argc = argc;
456
471#ifdef WINDOWSNT 457#ifdef WINDOWSNT
472 /* Must use argv0 converted to UTF-8, as it begets many standard 458 /* Must use argv[0] converted to UTF-8, as it begets many standard
473 file and directory names. */ 459 file and directory names. */
474 { 460 {
475 char argv0_1[MAX_UTF8_PATH]; 461 char argv0[MAX_UTF8_PATH];
476 462
477 /* Avoid calling 'openp' below, as we aren't ready for that yet: 463 if (filename_from_ansi (argv[0], argv0) == 0)
478 emacs_dir is not yet defined in the environment, and therefore
479 emacs_root_dir, called by expand-file-name, will abort. */
480 if (!IS_ABSOLUTE_FILE_NAME (argv0))
481 argv0 = w32_my_exename ();
482
483 if (filename_from_ansi (argv0, argv0_1) == 0)
484 raw_name = build_unibyte_string (argv0_1);
485 else
486 raw_name = build_unibyte_string (argv0); 464 raw_name = build_unibyte_string (argv0);
465 else
466 raw_name = build_unibyte_string (argv[0]);
487 } 467 }
488#else 468#else
489 raw_name = build_unibyte_string (argv0); 469 raw_name = build_unibyte_string (argv[0]);
490#endif 470#endif
491 471
492 /* Add /: to the front of the name 472 /* Add /: to the front of the name
@@ -495,26 +475,16 @@ set_invocation_vars (char *argv0, char const *original_pwd)
495 if (! NILP (handler)) 475 if (! NILP (handler))
496 raw_name = concat2 (slash_colon, raw_name); 476 raw_name = concat2 (slash_colon, raw_name);
497 477
498 char *filename = real_filename (SSDATA (raw_name));
499 raw_name = build_unibyte_string (filename);
500 xfree (filename);
501
502 Vinvocation_name = Ffile_name_nondirectory (raw_name); 478 Vinvocation_name = Ffile_name_nondirectory (raw_name);
503 Vinvocation_directory = Ffile_name_directory (raw_name); 479 Vinvocation_directory = Ffile_name_directory (raw_name);
504 480
505#ifdef WINDOWSNT 481 /* If we got no directory in argv[0], search PATH to find where
506 eassert (!NILP (Vinvocation_directory)
507 && !NILP (Ffile_name_absolute_p (Vinvocation_directory)));
508#endif
509
510 /* If we got no directory in argv0, search PATH to find where
511 Emacs actually came from. */ 482 Emacs actually came from. */
512 if (NILP (Vinvocation_directory)) 483 if (NILP (Vinvocation_directory))
513 { 484 {
514 Lisp_Object found; 485 Lisp_Object found;
515 int yes = 486 int yes = openp (Vexec_path, Vinvocation_name, Vexec_suffixes,
516 openp (Vexec_path, Vinvocation_name, Vexec_suffixes, &found, 487 &found, make_fixnum (X_OK), false, false);
517 make_fixnum (X_OK), false, false);
518 if (yes == 1) 488 if (yes == 1)
519 { 489 {
520 /* Add /: to the front of the name 490 /* Add /: to the front of the name
@@ -536,38 +506,6 @@ set_invocation_vars (char *argv0, char const *original_pwd)
536 506
537 Vinvocation_directory = Fexpand_file_name (Vinvocation_directory, odir); 507 Vinvocation_directory = Fexpand_file_name (Vinvocation_directory, odir);
538 } 508 }
539}
540
541/* Initialize a number of variables (ultimately
542 'Vinvocation_directory') needed by pdumper to complete native code
543 load. */
544
545void
546init_vars_for_load (char *argv0, char const *original_pwd)
547{
548 /* This function is called from within pdumper while loading (as
549 soon as we are able to allocate) or later during boot if pdumper
550 is not used. No need to run it twice. */
551 static bool double_run_guard;
552 if (double_run_guard)
553 return;
554 double_run_guard = true;
555
556 init_callproc_1 (); /* Must precede init_cmdargs and init_sys_modes. */
557 set_invocation_vars (argv0, original_pwd);
558}
559
560
561/* Code for dealing with Lisp access to the Unix command line. */
562static void
563init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd)
564{
565 int i;
566 Lisp_Object name, dir;
567 ptrdiff_t count = SPECPDL_INDEX ();
568
569 initial_argv = argv;
570 initial_argc = argc;
571 509
572 Vinstallation_directory = Qnil; 510 Vinstallation_directory = Qnil;
573 511
@@ -801,6 +739,8 @@ load_pdump_find_executable (char const *argv0, ptrdiff_t *candidate_size)
801 implementation of malloc, since the caller calls our free. */ 739 implementation of malloc, since the caller calls our free. */
802#ifdef WINDOWSNT 740#ifdef WINDOWSNT
803 char *prog_fname = w32_my_exename (); 741 char *prog_fname = w32_my_exename ();
742 if (prog_fname)
743 *candidate_size = strlen (prog_fname) + 1;
804 return prog_fname ? xstrdup (prog_fname) : NULL; 744 return prog_fname ? xstrdup (prog_fname) : NULL;
805#else /* !WINDOWSNT */ 745#else /* !WINDOWSNT */
806 char *candidate = NULL; 746 char *candidate = NULL;
@@ -846,7 +786,19 @@ load_pdump_find_executable (char const *argv0, ptrdiff_t *candidate_size)
846 struct stat st; 786 struct stat st;
847 if (file_access_p (candidate, X_OK) 787 if (file_access_p (candidate, X_OK)
848 && stat (candidate, &st) == 0 && S_ISREG (st.st_mode)) 788 && stat (candidate, &st) == 0 && S_ISREG (st.st_mode))
849 return candidate; 789 {
790 /* People put on PATH a symlink to the real Emacs
791 executable, with all the auxiliary files where the real
792 executable lives. Support that. */
793 if (lstat (candidate, &st) == 0 && S_ISLNK (st.st_mode))
794 {
795 char *real_name = realpath (candidate, NULL);
796
797 if (real_name)
798 return real_name;
799 }
800 return candidate;
801 }
850 *candidate = '\0'; 802 *candidate = '\0';
851 } 803 }
852 while (*path++ != '\0'); 804 while (*path++ != '\0');
@@ -856,10 +808,11 @@ load_pdump_find_executable (char const *argv0, ptrdiff_t *candidate_size)
856} 808}
857 809
858static void 810static void
859load_pdump (int argc, char **argv, char const *original_pwd) 811load_pdump (int argc, char **argv)
860{ 812{
861 const char *const suffix = ".pdmp"; 813 const char *const suffix = ".pdmp";
862 int result; 814 int result;
815 char *emacs_executable = argv[0];
863 const char *strip_suffix = 816 const char *strip_suffix =
864#if defined DOS_NT || defined CYGWIN 817#if defined DOS_NT || defined CYGWIN
865 ".exe" 818 ".exe"
@@ -889,9 +842,19 @@ load_pdump (int argc, char **argv, char const *original_pwd)
889 skip_args++; 842 skip_args++;
890 } 843 }
891 844
845 /* Where's our executable? */
846 ptrdiff_t bufsize, exec_bufsize;
847 emacs_executable = load_pdump_find_executable (argv[0], &bufsize);
848 exec_bufsize = bufsize;
849
850 /* If we couldn't find our executable, go straight to looking for
851 the dump in the hardcoded location. */
852 if (!(emacs_executable && *emacs_executable))
853 goto hardcoded;
854
892 if (dump_file) 855 if (dump_file)
893 { 856 {
894 result = pdumper_load (dump_file, argv[0], original_pwd); 857 result = pdumper_load (dump_file, emacs_executable);
895 858
896 if (result != PDUMPER_LOAD_SUCCESS) 859 if (result != PDUMPER_LOAD_SUCCESS)
897 fatal ("could not load dump file \"%s\": %s", 860 fatal ("could not load dump file \"%s\": %s",
@@ -905,42 +868,29 @@ load_pdump (int argc, char **argv, char const *original_pwd)
905 so we can't use decode_env_path. We're working in whatever 868 so we can't use decode_env_path. We're working in whatever
906 encoding the system natively uses for filesystem access, so 869 encoding the system natively uses for filesystem access, so
907 there's no need for character set conversion. */ 870 there's no need for character set conversion. */
908 ptrdiff_t bufsize; 871 ptrdiff_t exenamelen = strlen (emacs_executable);
909 dump_file = load_pdump_find_executable (argv[0], &bufsize); 872 if (strip_suffix)
910 873 {
911 /* If we couldn't find our executable, go straight to looking for 874 ptrdiff_t strip_suffix_length = strlen (strip_suffix);
912 the dump in the hardcoded location. */ 875 ptrdiff_t prefix_length = exenamelen - strip_suffix_length;
913 if (dump_file && *dump_file) 876 if (0 <= prefix_length
914 { 877 && !memcmp (&emacs_executable[prefix_length], strip_suffix,
915 char *real_exename = real_filename (dump_file); 878 strip_suffix_length))
916 xfree (dump_file); 879 exenamelen = prefix_length;
917 dump_file = real_exename; 880 }
918 ptrdiff_t exenamelen = strlen (dump_file); 881 ptrdiff_t needed = exenamelen + strlen (suffix) + 1;
919#ifndef WINDOWSNT 882 dump_file = xpalloc (NULL, &bufsize, needed - bufsize, -1, 1);
920 bufsize = exenamelen + 1; 883 memcpy (dump_file, emacs_executable, exenamelen);
921#endif 884 strcpy (dump_file + exenamelen, suffix);
922 if (strip_suffix) 885 result = pdumper_load (dump_file, emacs_executable);
923 { 886 if (result == PDUMPER_LOAD_SUCCESS)
924 ptrdiff_t strip_suffix_length = strlen (strip_suffix); 887 goto out;
925 ptrdiff_t prefix_length = exenamelen - strip_suffix_length; 888
926 if (0 <= prefix_length 889 if (result != PDUMPER_LOAD_FILE_NOT_FOUND)
927 && !memcmp (&dump_file[prefix_length], strip_suffix, 890 fatal ("could not load dump file \"%s\": %s",
928 strip_suffix_length)) 891 dump_file, dump_error_to_string (result));
929 exenamelen = prefix_length; 892
930 } 893 hardcoded:
931 ptrdiff_t needed = exenamelen + strlen (suffix) + 1;
932 if (bufsize < needed)
933 dump_file = xpalloc (dump_file, &bufsize, needed - bufsize, -1, 1);
934 strcpy (dump_file + exenamelen, suffix);
935 result = pdumper_load (dump_file, argv[0], original_pwd);
936 if (result == PDUMPER_LOAD_SUCCESS)
937 goto out;
938
939 if (result != PDUMPER_LOAD_FILE_NOT_FOUND)
940 fatal ("could not load dump file \"%s\": %s",
941 dump_file, dump_error_to_string (result));
942 }
943
944#ifdef WINDOWSNT 894#ifdef WINDOWSNT
945 /* On MS-Windows, PATH_EXEC normally starts with a literal 895 /* On MS-Windows, PATH_EXEC normally starts with a literal
946 "%emacs_dir%", so it will never work without some tweaking. */ 896 "%emacs_dir%", so it will never work without some tweaking. */
@@ -951,11 +901,11 @@ load_pdump (int argc, char **argv, char const *original_pwd)
951 "emacs.pdmp" so that the Emacs binary still works if the user 901 "emacs.pdmp" so that the Emacs binary still works if the user
952 copies and renames it. */ 902 copies and renames it. */
953 const char *argv0_base = "emacs"; 903 const char *argv0_base = "emacs";
954 ptrdiff_t needed = (strlen (path_exec) 904 needed = (strlen (path_exec)
955 + 1 905 + 1
956 + strlen (argv0_base) 906 + strlen (argv0_base)
957 + strlen (suffix) 907 + strlen (suffix)
958 + 1); 908 + 1);
959 if (bufsize < needed) 909 if (bufsize < needed)
960 { 910 {
961 xfree (dump_file); 911 xfree (dump_file);
@@ -963,7 +913,19 @@ load_pdump (int argc, char **argv, char const *original_pwd)
963 } 913 }
964 sprintf (dump_file, "%s%c%s%s", 914 sprintf (dump_file, "%s%c%s%s",
965 path_exec, DIRECTORY_SEP, argv0_base, suffix); 915 path_exec, DIRECTORY_SEP, argv0_base, suffix);
966 result = pdumper_load (dump_file, argv[0], original_pwd); 916 /* Assume the Emacs binary lives in a sibling directory as set up by
917 the default installation configuration. */
918 const char *go_up = "../../../../bin/";
919 needed += strlen (strip_suffix) - strlen (suffix) + strlen (go_up);
920 if (exec_bufsize < needed)
921 {
922 xfree (emacs_executable);
923 emacs_executable = xpalloc (NULL, &exec_bufsize, needed - exec_bufsize,
924 -1, 1);
925 }
926 sprintf (emacs_executable, "%s%c%s%s%s",
927 path_exec, DIRECTORY_SEP, go_up, argv0_base, strip_suffix);
928 result = pdumper_load (dump_file, emacs_executable);
967 929
968 if (result == PDUMPER_LOAD_FILE_NOT_FOUND) 930 if (result == PDUMPER_LOAD_FILE_NOT_FOUND)
969 { 931 {
@@ -998,7 +960,7 @@ load_pdump (int argc, char **argv, char const *original_pwd)
998#endif 960#endif
999 sprintf (dump_file, "%s%c%s%s", 961 sprintf (dump_file, "%s%c%s%s",
1000 path_exec, DIRECTORY_SEP, argv0_base, suffix); 962 path_exec, DIRECTORY_SEP, argv0_base, suffix);
1001 result = pdumper_load (dump_file, argv[0], original_pwd); 963 result = pdumper_load (dump_file, emacs_executable);
1002 } 964 }
1003 965
1004 if (result != PDUMPER_LOAD_SUCCESS) 966 if (result != PDUMPER_LOAD_SUCCESS)
@@ -1010,6 +972,7 @@ load_pdump (int argc, char **argv, char const *original_pwd)
1010 972
1011 out: 973 out:
1012 xfree (dump_file); 974 xfree (dump_file);
975 xfree (emacs_executable);
1013} 976}
1014#endif /* HAVE_PDUMPER */ 977#endif /* HAVE_PDUMPER */
1015 978
@@ -1320,10 +1283,9 @@ main (int argc, char **argv)
1320 w32_init_main_thread (); 1283 w32_init_main_thread ();
1321#endif 1284#endif
1322 1285
1323 emacs_wd = emacs_get_current_dir_name ();
1324#ifdef HAVE_PDUMPER 1286#ifdef HAVE_PDUMPER
1325 if (attempt_load_pdump) 1287 if (attempt_load_pdump)
1326 load_pdump (argc, argv, emacs_wd); 1288 load_pdump (argc, argv);
1327#endif 1289#endif
1328 1290
1329 argc = maybe_disable_address_randomization (argc, argv); 1291 argc = maybe_disable_address_randomization (argc, argv);
@@ -1395,6 +1357,7 @@ main (int argc, char **argv)
1395 exit (0); 1357 exit (0);
1396 } 1358 }
1397 1359
1360 emacs_wd = emacs_get_current_dir_name ();
1398#ifdef HAVE_PDUMPER 1361#ifdef HAVE_PDUMPER
1399 if (dumped_with_pdumper_p ()) 1362 if (dumped_with_pdumper_p ())
1400 pdumper_record_wd (emacs_wd); 1363 pdumper_record_wd (emacs_wd);
@@ -2038,8 +2001,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
2038 /* Init buffer storage and default directory of main buffer. */ 2001 /* Init buffer storage and default directory of main buffer. */
2039 init_buffer (); 2002 init_buffer ();
2040 2003
2041 init_vars_for_load (argv[0], original_pwd);
2042
2043 /* Must precede init_lread. */ 2004 /* Must precede init_lread. */
2044 init_cmdargs (argc, argv, skip_args, original_pwd); 2005 init_cmdargs (argc, argv, skip_args, original_pwd);
2045 2006
diff --git a/src/lisp.h b/src/lisp.h
index 474e49c8e1e..f83c55f827d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4450,7 +4450,6 @@ extern bool display_arg;
4450extern Lisp_Object decode_env_path (const char *, const char *, bool); 4450extern Lisp_Object decode_env_path (const char *, const char *, bool);
4451extern Lisp_Object empty_unibyte_string, empty_multibyte_string; 4451extern Lisp_Object empty_unibyte_string, empty_multibyte_string;
4452extern AVOID terminate_due_to_signal (int, int); 4452extern AVOID terminate_due_to_signal (int, int);
4453extern void init_vars_for_load (char *, char const *);
4454#ifdef WINDOWSNT 4453#ifdef WINDOWSNT
4455extern Lisp_Object Vlibrary_cache; 4454extern Lisp_Object Vlibrary_cache;
4456#endif 4455#endif
diff --git a/src/pdumper.c b/src/pdumper.c
index dc893c59bfa..c9285ddbc78 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)
4356} 4356}
4357 4357
4358 4358
4359#ifdef HAVE_NATIVE_COMP
4360/* This records the directory where the Emacs executable lives, to be
4361 used for locating the native-lisp directory from which we need to
4362 load the preloaded *.eln files. See pdumper_set_emacs_execdir
4363 below. */
4364static char *emacs_execdir;
4365static ptrdiff_t execdir_size;
4366static ptrdiff_t execdir_len;
4367#endif
4368
4359/* Dump runtime */ 4369/* Dump runtime */
4360enum dump_memory_protection 4370enum dump_memory_protection
4361{ 4371{
@@ -5269,35 +5279,54 @@ dump_do_dump_relocation (const uintptr_t dump_base,
5269 struct Lisp_Native_Comp_Unit *comp_u = 5279 struct Lisp_Native_Comp_Unit *comp_u =
5270 dump_ptr (dump_base, reloc_offset); 5280 dump_ptr (dump_base, reloc_offset);
5271 comp_u->lambda_gc_guard_h = CALLN (Fmake_hash_table, QCtest, Qeq); 5281 comp_u->lambda_gc_guard_h = CALLN (Fmake_hash_table, QCtest, Qeq);
5272 if (!CONSP (comp_u->file)) 5282 if (STRINGP (comp_u->file))
5273 error ("Trying to load incoherent dumped eln file %s", 5283 error ("Trying to load incoherent dumped eln file %s",
5274 SSDATA (comp_u->file)); 5284 SSDATA (comp_u->file));
5275 5285
5286 /* emacs_execdir is always unibyte, but the file names in
5287 comp_u->file could be multibyte, so we need to encode
5288 them. */
5289 Lisp_Object cu_file1 = ENCODE_FILE (XCAR (comp_u->file));
5290 Lisp_Object cu_file2 = ENCODE_FILE (XCDR (comp_u->file));
5291 ptrdiff_t fn1_len = SBYTES (cu_file1), fn2_len = SBYTES (cu_file2);
5292 Lisp_Object eln_fname;
5293 char *fndata;
5294
5276 /* Check just once if this is a local build or Emacs was installed. */ 5295 /* Check just once if this is a local build or Emacs was installed. */
5296 /* Can't use expand-file-name here, because we are too early
5297 in the startup, and we will crash at least on WINDOWSNT. */
5277 if (installation_state == UNKNOWN) 5298 if (installation_state == UNKNOWN)
5278 { 5299 {
5279 /* Can't use expand-file-name here, because we are too 5300 eln_fname = make_uninit_string (execdir_len + fn1_len);
5280 early in the startup, and we will crash at least on 5301 fndata = SSDATA (eln_fname);
5281 WINDOWSNT. */ 5302 memcpy (fndata, emacs_execdir, execdir_len);
5282 Lisp_Object fname = 5303 memcpy (fndata + execdir_len, SSDATA (cu_file1), fn1_len);
5283 concat2 (Vinvocation_directory, XCAR (comp_u->file)); 5304 if (file_access_p (fndata, F_OK))
5284 if (file_access_p (SSDATA (ENCODE_FILE (fname)), F_OK)) 5305 installation_state = INSTALLED;
5285 {
5286 installation_state = INSTALLED;
5287 fixup_eln_load_path (XCAR (comp_u->file));
5288 }
5289 else 5306 else
5290 { 5307 {
5308 eln_fname = make_uninit_string (execdir_len + fn2_len);
5309 fndata = SSDATA (eln_fname);
5310 memcpy (fndata, emacs_execdir, execdir_len);
5311 memcpy (fndata + execdir_len, SSDATA (cu_file2), fn2_len);
5291 installation_state = LOCAL_BUILD; 5312 installation_state = LOCAL_BUILD;
5292 fixup_eln_load_path (XCDR (comp_u->file));
5293 } 5313 }
5314 fixup_eln_load_path (eln_fname);
5315 }
5316 else
5317 {
5318 ptrdiff_t fn_len =
5319 installation_state == INSTALLED ? fn1_len : fn2_len;
5320 Lisp_Object cu_file =
5321 installation_state == INSTALLED ? cu_file1 : cu_file2;
5322 eln_fname = make_uninit_string (execdir_len + fn_len);
5323 fndata = SSDATA (eln_fname);
5324 memcpy (fndata, emacs_execdir, execdir_len);
5325 memcpy (fndata + execdir_len, SSDATA (cu_file), fn_len);
5294 } 5326 }
5295 5327
5296 comp_u->file = 5328 comp_u->file = eln_fname;
5297 concat2 (Vinvocation_directory, 5329 comp_u->handle = dynlib_open (SSDATA (eln_fname));
5298 installation_state == INSTALLED
5299 ? XCAR (comp_u->file) : XCDR (comp_u->file));
5300 comp_u->handle = dynlib_open (SSDATA (ENCODE_FILE (comp_u->file)));
5301 if (!comp_u->handle) 5330 if (!comp_u->handle)
5302 error ("%s", dynlib_error ()); 5331 error ("%s", dynlib_error ());
5303 load_comp_unit (comp_u, true, false); 5332 load_comp_unit (comp_u, true, false);
@@ -5435,6 +5464,26 @@ dump_do_all_emacs_relocations (const struct dump_header *const header,
5435 dump_do_emacs_relocation (dump_base, r[i]); 5464 dump_do_emacs_relocation (dump_base, r[i]);
5436} 5465}
5437 5466
5467#ifdef HAVE_NATIVE_COMP
5468/* Compute and record the directory of the Emacs executable given the
5469 file name of that executable. */
5470static void
5471pdumper_set_emacs_execdir (char *emacs_executable)
5472{
5473 char *p = emacs_executable + strlen (emacs_executable);
5474
5475 while (p > emacs_executable
5476 && !IS_DIRECTORY_SEP (p[-1]))
5477 --p;
5478 eassert (p > emacs_executable);
5479 emacs_execdir = xpalloc (emacs_execdir, &execdir_size,
5480 p - emacs_executable + 1 - execdir_size, -1, 1);
5481 memcpy (emacs_execdir, emacs_executable, p - emacs_executable);
5482 execdir_len = p - emacs_executable;
5483 emacs_execdir[execdir_len] = '\0';
5484}
5485#endif
5486
5438enum dump_section 5487enum dump_section
5439 { 5488 {
5440 DS_HOT, 5489 DS_HOT,
@@ -5451,7 +5500,7 @@ static Lisp_Object *pdumper_hashes = &zero_vector;
5451 N.B. We run very early in initialization, so we can't use lisp, 5500 N.B. We run very early in initialization, so we can't use lisp,
5452 unwinding, xmalloc, and so on. */ 5501 unwinding, xmalloc, and so on. */
5453int 5502int
5454pdumper_load (const char *dump_filename, char *argv0, char const *original_pwd) 5503pdumper_load (const char *dump_filename, char *argv0)
5455{ 5504{
5456 intptr_t dump_size; 5505 intptr_t dump_size;
5457 struct stat stat; 5506 struct stat stat;
@@ -5607,9 +5656,11 @@ pdumper_load (const char *dump_filename, char *argv0, char const *original_pwd)
5607 for (int i = 0; i < nr_dump_hooks; ++i) 5656 for (int i = 0; i < nr_dump_hooks; ++i)
5608 dump_hooks[i] (); 5657 dump_hooks[i] ();
5609 5658
5610 /* Once we can allocate and before loading .eln files we must set 5659#ifdef HAVE_NATIVE_COMP
5611 Vinvocation_directory (.eln paths are relative to it). */ 5660 pdumper_set_emacs_execdir (argv0);
5612 init_vars_for_load (argv0, original_pwd); 5661#else
5662 (void) argv0;
5663#endif
5613 5664
5614 dump_do_all_dump_reloc_for_phase (header, dump_base, LATE_RELOCS); 5665 dump_do_all_dump_reloc_for_phase (header, dump_base, LATE_RELOCS);
5615 dump_do_all_dump_reloc_for_phase (header, dump_base, VERY_LATE_RELOCS); 5666 dump_do_all_dump_reloc_for_phase (header, dump_base, VERY_LATE_RELOCS);
diff --git a/src/pdumper.h b/src/pdumper.h
index 49e6739b0dc..deec9af046d 100644
--- a/src/pdumper.h
+++ b/src/pdumper.h
@@ -140,8 +140,7 @@ enum pdumper_load_result
140 PDUMPER_LOAD_ERROR /* Must be last, as errno may be added. */ 140 PDUMPER_LOAD_ERROR /* Must be last, as errno may be added. */
141 }; 141 };
142 142
143int pdumper_load (const char *dump_filename, char *argv0, 143int pdumper_load (const char *dump_filename, char *argv0);
144 char const *original_pwd);
145 144
146struct pdumper_loaded_dump 145struct pdumper_loaded_dump
147{ 146{