2 * main() entry point for a stand alone lisp image.
4 * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/lisp.c,v 1.84 2011/09/01 05:18:26 rtoy Exp $
18 #include "internals.h"
23 #include "interrupt.h"
35 #if defined(FEATURE_EXECUTABLE)
40 #include <sys/utsname.h>
43 #if defined(__linux__)
49 /* SIGINT handler that invokes the monitor. */
52 sigint_handler(HANDLER_ARGS)
54 os_context_t *os_context = (os_context_t *) context;
58 printf("\nSIGINT hit at 0x%08lX\n", (unsigned long) SC_PC(os_context));
62 /* Not static, because we want to be able to call it from lisp land. */
66 install_handler(SIGINT, sigint_handler);
70 /* Noise to convert argv and envp into lists. */
73 alloc_str_list(const char *list[])
75 lispobj result, newcons;
81 result = newcons = alloc_cons(alloc_string(*list++), NIL);
83 while (*list != NULL) {
84 ptr = (struct cons *) PTR(newcons);
85 newcons = alloc_cons(alloc_string(*list++), NIL);
93 /* Default paths for CMUCLLIB */
94 static char *cmucllib_search_list[] = {
98 "/usr/local/lib/cmucl/lib",
104 getcwd_or_die(char* buf, size_t size)
106 char *result = getcwd(buf, size);
108 if (result == NULL) {
109 perror("Cannot get cwd");
114 /* Set this to see how we're doing our search */
115 int debug_lisp_search = FALSE;
118 * Define this to get some debugging printfs for searching for the
119 * lisp core file. Sometimes needed because you can't debug this with
120 * gdb which always seems to set argv[0] to the full pathname.
123 /* #define DEBUG_LISP_SEARCH */
126 * From the current location of the lisp executable, create a suitable
127 * default for CMUCLLIB
130 default_cmucllib(const char *argv0arg)
135 char *argv0_dir = strdup(argv0arg);
138 * From argv[0], create the appropriate directory by lopping off the
142 p0 = strrchr(argv0_dir, '/');
145 } else if (p0 != argv0_dir) {
150 * Create the full pathname of the directory containing the
151 * executable. argv[0] can be an absolute or relative path.
153 if (debug_lisp_search) {
154 fprintf(stderr, "argv[0] = %s\n", argv0arg);
155 fprintf(stderr, "argv_dir = %s\n", argv0_dir);
159 if (argv0_dir[0] == '/') {
160 cwd = malloc(strlen(argv0_dir) + 2);
161 strcpy(cwd, argv0_dir);
163 if (debug_lisp_search) {
164 fprintf(stderr, "absolute path, argv[0] = %s\n", cwd);
167 } else if (*argv0_dir != '\0') {
169 * argv[0] is a relative path. Get the current directory and
170 * append argv[0], after stripping off the executable name.
172 cwd = malloc(FILENAME_MAX + strlen(argv0_dir) + 100);
173 getcwd_or_die(cwd, FILENAME_MAX);
175 if (*argv0_dir != '\0') {
176 strcat(cwd, argv0_dir);
179 if (debug_lisp_search) {
180 fprintf(stderr, "relative path, argv[0] = %s\n", cwd);
184 * argv[0] is someplace on the user's PATH
187 char *path = getenv("PATH");
188 char *p1, *p2 = NULL;
191 if (debug_lisp_search) {
192 fprintf(stderr, "User's PATH = %s\n", path ? path : "<NULL>");
195 cwd = malloc(FILENAME_MAX + strlen(argv0arg) + 100);
199 const char *ptr = (p0 != NULL) ? p0 : argv0arg;
201 for (p1 = path; *p1 != '\0'; p1 = p2) {
202 p2 = strchr(p1, ':');
204 p2 = p1 + strlen(p1);
205 strncpy(cwd, p1, p2 - p1);
207 cwd[p2 - p1 + 1] = '\0';
208 strcpy(cwd + (p2 - p1 + 1), ptr);
210 if (debug_lisp_search) {
211 fprintf(stderr, "User's PATH, trying %s\n", cwd);
214 if (stat(cwd, &buf) == 0) {
216 if (debug_lisp_search) {
217 fprintf(stderr, "User's PATH, found %s\n", cwd);
219 if (access(cwd, X_OK) == 0) {
222 if (debug_lisp_search) {
224 " But not executable. Continuing...\n");
235 if ((p1 == p2) || (p2 == NULL)) {
238 cwd[p2 - p1 + 1] = '\0';
240 if (debug_lisp_search) {
241 fprintf(stderr, "User's PATH, Final cwd %s\n", cwd);
247 /* Create the appropriate value for CMUCLLIB */
254 /* First figure out how much space we need */
257 cwd_len = strlen(cwd);
259 ptr = cmucllib_search_list;
261 while (*ptr != NULL) {
262 /* Plus 2 for the ":" and "/" we need to add */
263 total_len += strlen(*ptr) + cwd_len + 2;
267 /* Create the colon separated list of directories */
269 defpath = malloc(total_len + 1);
272 ptr = cmucllib_search_list;
273 while (*ptr != NULL) {
274 if (*ptr[0] != '/') {
275 strcat(defpath, cwd);
278 strcat(defpath, *ptr);
280 if (ptr[1] != NULL) {
281 strcat(defpath, ":");
287 if (strlen(defpath) > total_len) {
295 return (const char *) defpath;
299 * Search the a core file with the name given by default_core in the
300 * colon-separated list of directories given by lib.
302 * Return the full path, if found, or NULL if not.
306 search_core(const char *lib, const char *default_core)
312 * A buffer that's large enough to hold lib, default_core, a
313 * slash, and a the string terminator
315 buf = malloc(strlen(lib) + strlen(default_core) + 2);
320 * Extract out everything to the first colon, then append a
321 * "/" and the core name. See if the file exists.
323 while (*lib != '\0' && *lib != ':')
325 if (dst != buf && dst[-1] != '/')
327 strcpy(dst, default_core);
328 /* If it exists, we are done! */
330 if (debug_lisp_search) {
331 fprintf(stderr, "Looking at `%s'\n", buf);
334 if (access(buf, R_OK) == 0) {
335 if (debug_lisp_search) {
336 fprintf(stderr, "Found it!\n");
341 if (debug_lisp_search) {
342 fprintf(stderr, "Found it, but we can't read it!\n");
345 } while (*lib++ == ':');
352 * Given the path to a core file, prepend the absolute location of the
353 * core file to the lib path.
355 * Return the new lib path.
358 prepend_core_path(const char *lib, const char *corefile)
360 char cwd[FILENAME_MAX];
365 if (*corefile == '/') {
366 path = strdup(corefile);
369 * We have a relative path for the corefile. Prepend our current
370 * directory to get the full path.
372 getcwd_or_die(cwd, FILENAME_MAX);
373 path = malloc(FILENAME_MAX + strlen(corefile) + 2);
376 strcat(path, corefile);
380 * Now remove the name portion by finding the last slash.
382 sep = strrchr(path, '/');
387 result = malloc(strlen(path) + strlen(lib) + 2);
388 strcpy(result, path);
393 return (const char *) result; /* Don't let the caller modify the buffer we built */
397 * The value of the variable builtin_image_flag indicate whether the
398 * executable contains the lisp image or not. The variable
399 * initial_function_addr indicates the address of the initial
400 * function. How these are interpreted depends on the system.
402 * For Linux/x86, Darwin/x86, and Solaris/sparc, the
403 * builtin_image_flag is a normal symbol mapped into a normal data
404 * area. If true, the executable contains the lisp image. Likewise,
405 * initial_function_addr is a symbol mapped into a normal data area.
406 * The value of this variable is the address of the initial function.
408 * For other systems, we use the linker to set the value of the symbol.
409 * But the symbol is an address, not a variable value. So for this to
410 * work as a flag, it must end up pointing to a valid place in memory
411 * or we'll get a bus error or segmentation violation when we check
412 * it. If the lisp image is built in, we'll set this symbol to point
413 * to the beginning of the process.
415 * We also use the linker to set initial_function_addr so that if the
416 * lisp core is built in, taking the address of initial_function_addr
417 * will give the address of the initial function.
419 * The details of how these variables are set up are in
420 * tools/linker.sh and tools/linker-x86.sh. Which script is used is
421 * set in src/lisp/elf.h.
424 extern int builtin_image_flag;
425 extern long initial_function_addr;
427 fpu_mode_t fpu_mode = AUTO;
430 locate_core(const char* cmucllib, const char* core, const char* default_core)
433 if (getenv("CMUCLCORE") == NULL) {
434 core = search_core(cmucllib, default_core);
436 core = getenv("CMUCLCORE");
440 if (access(core, R_OK) != 0) {
448 core_failure(const char* core, const char* argv[])
451 fprintf(stderr, "Cannot find core file");
453 fprintf(stderr, ": `%s'", core);
455 fprintf(stderr, "\n");
456 fprintf(stderr, "Based on lisp binary path `%s'\n", argv[0]);
461 main(int argc, const char *argv[], const char *envp[])
463 const char *arg, **argptr;
464 const char *core = NULL;
465 const char *default_core;
466 const char *lib = NULL;
467 const char *cmucllib = NULL;
468 const char *unidata = NULL;
470 fpu_mode_t fpu_type = AUTO;
472 lispobj initial_function = 0;
474 if (builtin_image_flag != 0) {
475 #if defined(SOLARIS) || (defined(i386) && (defined(__linux__) || defined(DARWIN) || defined(__FreeBSD__) || defined(__NetBSD__)))
476 initial_function = (lispobj) initial_function_addr;
478 initial_function = (lispobj) & initial_function_addr;
484 * Do any special OS initialization that needs to be done early.
485 * In particular, on Linux, we might re-exec ourselves to set our
486 * personality correctly. Not normally a problem, but this does
487 * cause any output to happen twice. That can be confusing.
489 * So make sure we don't do any output before this point!
492 os_init0(argv, envp);
497 set_lossage_handler(ldb_monitor);
501 #ifdef DEFAULT_DYNAMIC_SPACE_SIZE
502 dynamic_space_size = DEFAULT_DYNAMIC_SPACE_SIZE;
504 dynamic_space_size = DYNAMIC_SPACE_SIZE;
506 #ifdef DEFAULT_READ_ONLY_SIZE
507 read_only_space_size = DEFAULT_READ_ONLY_SIZE;
509 read_only_space_size = READ_ONLY_SPACE_SIZE;
511 #ifdef DEFAULT_STATIC_SIZE
512 static_space_size = DEFAULT_STATIC_SIZE;
514 static_space_size = STATIC_SPACE_SIZE;
516 #ifdef DEFAULT_BINDING_SIZE
517 binding_stack_size = DEFAULT_BINDING_SIZE;
519 binding_stack_size = BINDING_STACK_SIZE;
521 #ifdef DEFAULT_CONTROL_SIZE
522 control_stack_size = DEFAULT_CONTROL_SIZE;
524 control_stack_size = CONTROL_STACK_SIZE;
528 while ((arg = *++argptr) != NULL) {
529 if (strcmp(arg, "-core") == 0) {
530 if (builtin_image_flag) {
532 "Warning: specifying a core file with an executable image is unusual,\nbut should work.\n");
533 builtin_image_flag = 0;
537 fprintf(stderr, "can only specify one core file.\n");
543 "-core must be followed by the name of the core file to use.\n");
546 } else if (strcmp(arg, "-lib") == 0) {
550 "-lib must be followed by a string denoting the CMUCL library path.\n");
553 } else if (strcmp(arg, "-read-only-space-size") == 0) {
554 const char *str = *++argptr;
558 "-read-only-space-size must be followed by the size in MBytes.\n");
561 read_only_space_size = atoi(str) * 1024 * 1024;
562 if (read_only_space_size > READ_ONLY_SPACE_SIZE) {
564 "-read-only-space-size must be no greater than %lu MBytes.\n",
565 READ_ONLY_SPACE_SIZE / (1024 * 1024UL));
566 fprintf(stderr, " Continuing with default size.\n");
567 read_only_space_size = READ_ONLY_SPACE_SIZE;
569 } else if (strcmp(arg, "-static-space-size") == 0) {
570 const char *str = *++argptr;
574 "-static-space-size must be followed by the size in MBytes.\n");
577 static_space_size = atoi(str) * 1024 * 1024;
578 if (static_space_size > STATIC_SPACE_SIZE) {
580 "-static-space-size must be no greater than %lu MBytes.\n",
581 STATIC_SPACE_SIZE / (1024 * 1024UL));
582 fprintf(stderr, " Continuing with default size.\n");
583 static_space_size = STATIC_SPACE_SIZE;
585 } else if (strcmp(arg, "-binding-stack-size") == 0) {
586 const char *str = *++argptr;
590 "-binding-stack-size must be followed by the size in MBytes.\n");
593 binding_stack_size = atoi(str) * 1024 * 1024;
594 if (binding_stack_size > BINDING_STACK_SIZE) {
596 "-binding-stack-size must be no greater than %lu MBytes.\n",
597 BINDING_STACK_SIZE / (1024 * 1024UL));
598 fprintf(stderr, " Continuing with default size.\n");
599 binding_stack_size = BINDING_STACK_SIZE;
601 } else if (strcmp(arg, "-control-stack-size") == 0) {
602 const char *str = *++argptr;
606 "-control-stack-size must be followed by the size in MBytes.\n");
609 control_stack_size = atoi(str) * 1024 * 1024;
610 if (control_stack_size > CONTROL_STACK_SIZE) {
612 "-control-stack-size must be no greater than %lu MBytes.\n",
613 CONTROL_STACK_SIZE / (1024 * 1024UL));
614 fprintf(stderr, " Continuing with default size.\n");
615 control_stack_size = CONTROL_STACK_SIZE;
617 } else if (strcmp(arg, "-dynamic-space-size") == 0) {
623 "-dynamic-space-size must be followed by the size to use in MBytes.\n");
627 dynamic_space_size = atoi(str) * 1024 * 1024;
633 * Martin Rydstrom says core sizes that aren't a
634 * multiple of 8 MB eventually causes GC lossage with
635 * gencgc on Solaris 10. No one seems to understand why
636 * that is, but it is. So here we enforce the 8 MB
637 * boundary by rounding up the size. We print a warning
638 * message if we do have to round.
640 * We do this for all versions, since it doesn't hurt
641 * other versions of Solaris.
644 dynamic_space_size = (val + 7) & ~7;
646 if (val != dynamic_space_size) {
648 "Note: Rounding dynamic-space-size from %d MB to %d MB\n",
649 val, dynamic_space_size);
651 dynamic_space_size *= 1024 * 1024;
654 if (dynamic_space_size > DYNAMIC_SPACE_SIZE) {
656 "-dynamic-space-size must be no greater than %lu MBytes.\n",
657 DYNAMIC_SPACE_SIZE / (1024 * 1024UL));
660 } else if (strcmp(arg, "-monitor") == 0) {
662 } else if (strcmp(arg, "-debug-lisp-search") == 0) {
663 debug_lisp_search = TRUE;
664 } else if (strcmp(arg, "-unidata") == 0) {
668 else if (strcmp(arg, "-fpu") == 0) {
673 fprintf(stderr, "-fpu must be followed by the FPU type: auto, x87, sse2\n");
677 if (builtin_image_flag != 0) {
679 "Warning: -fpu cannot change the fpu mode of an executable image\n");
681 if (strcmp(str, "auto") == 0) {
683 } else if (strcmp(str, "x87") == 0) {
685 } else if (strcmp(str, "sse2") == 0) {
688 fprintf(stderr, "Unknown fpu type: `%s'. Using auto\n", str);
695 default_core = arch_init(fpu_mode);
697 if (default_core == NULL)
698 default_core = "lisp.core";
701 #if defined FEATURE_EXECUTABLE
702 if (builtin_image_flag != 0)
703 map_core_sections(argv[0]);
708 /* This is the first use of malloc() and must come after the
709 * static memory layout is mmapped to avoid conflicts with possible
710 * use of mmap() by malloc().
712 define_var("nil", NIL, TRUE);
713 define_var("t", T, TRUE);
716 * Basic algorithm for setting CMUCLLIB and CMUCLCORE, from Pierre
719 * if CMUCLLIB envvar is not set
720 * CMUCLLIB = our list of places to look
721 * if -core option/CMUCLCORE given
722 * CMUCLLIB = CMUCLLIB + full path to the specified core file
726 * if -core option/CMUCLCORE unset
727 * search for a core file (named whatever arch_init returns or
728 * lisp.core) somewhere in the CMUCLLIB list.
734 * give error message and die
737 * CMUCLCORE = where the core file was found/specced
741 * Set cmucllib to the -lib option, or to CMUCLLIB envvar. If
742 * neither are set, set cmucllib to our default search path.
745 cmucllib = strdup(lib);
749 libvar = getenv("CMUCLLIB");
750 if (libvar != NULL) {
751 cmucllib = strdup(libvar);
754 * The following doesn't make sense for executables. They
755 * need to use the saved library path from the lisp from
756 * which they were dumped.
758 if (builtin_image_flag == 0) {
759 const char *newlib = NULL;
762 * We need to use our default search path. If a core file
763 * is given, we prepend the directory of the core file to
766 cmucllib = default_cmucllib(argv[0]);
768 newlib = prepend_core_path(cmucllib, core);
769 } else if (getenv("CMUCLCORE") != NULL) {
770 core = getenv("CMUCLCORE");
771 newlib = prepend_core_path(cmucllib, core);
774 if (newlib != NULL) {
775 free((void *) cmucllib);
783 /* Only look for a core file if we're not using a built-in image. */
784 if (builtin_image_flag == 0) {
786 * If no core file specified, search for it in CMUCLLIB
788 const char* found_core;
790 found_core = locate_core(cmucllib, core, default_core);
792 if ((found_core == NULL) && (fpu_mode == AUTO)) {
794 * If we support SSE2 but couldn't find the SSE2 core, try
795 * to fall back to the x87 core.
797 found_core = locate_core(cmucllib, core, "lisp-x87.core");
798 if (found_core == NULL) {
799 core_failure(core, argv);
801 fprintf(stderr, "Warning: Chip supports SSE2, but could not find SSE2 core.\n");
802 fprintf(stderr, " Falling back to x87 core.\n");
806 core_failure(core, argv);
811 * The "core file" is the executable. We have to save the
812 * executable path because we operate on the executable file
820 if (builtin_image_flag != 0) {
821 extern int image_dynamic_space_size;
822 long allocation_pointer =
823 (long) dynamic_0_space + (int) image_dynamic_space_size;
824 #if defined(i386) || defined(__x86_64)
825 SetSymbolValue(ALLOCATION_POINTER, (lispobj) allocation_pointer);
827 current_dynamic_space_free_pointer = (lispobj *) allocation_pointer;
830 initial_function = load_core_file(core, &fpu_type);
834 if ((fpu_type == SSE2) && (!arch_support_sse2() || !os_support_sse2())) {
835 fprintf(stderr, "Core uses SSE2, but CPU/OS doesn't support SSE2. Exiting\n");
841 #if defined LINKAGE_TABLE
842 os_foreign_linkage_init();
843 #endif /* LINKAGE_TABLE */
846 gencgc_pickup_dynamic();
848 #if defined WANT_CGC && defined X86_CGC_ACTIVE_P
850 extern int use_cgc_p;
851 lispobj x = SymbolValue(X86_CGC_ACTIVE_P);
853 if (x != type_UnboundMarker && x != NIL)
854 use_cgc_p = 1; /* enable allocator */
859 #ifdef BINDING_STACK_POINTER
860 SetSymbolValue(BINDING_STACK_POINTER, (lispobj) binding_stack);
862 #if defined INTERNAL_GC_TRIGGER && !defined i386
863 SetSymbolValue(INTERNAL_GC_TRIGGER, make_fixnum(-1));
868 arch_install_interrupt_handlers();
869 os_install_interrupt_handlers();
871 #ifdef PSEUDO_ATOMIC_ATOMIC
872 /* Turn on pseudo atomic for when we call into lisp. */
873 SetSymbolValue(PSEUDO_ATOMIC_ATOMIC, make_fixnum(1));
874 SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(0));
877 /* Convert the argv and envp to something Lisp can grok. */
878 SetSymbolValue(LISP_COMMAND_LINE_LIST, alloc_str_list(argv));
879 SetSymbolValue(LISP_ENVIRONMENT_LIST, alloc_str_list(envp));
881 /* Set cmucllib and cmuclcore appropriately */
883 * This test will preserve the library: search list dumped with
884 * the executable unless the user specifically overrides it with
885 * the -lib flag or by setting the CMUCLLIB environment variable.
889 SetSymbolValue(CMUCL_LIB, alloc_string(cmucllib));
892 SetSymbolValue(CMUCL_CORE_PATH, alloc_string(core));
895 * Parse the command line again, picking up values that override
896 * those loaded from the core.
900 while ((arg = *++argptr) != NULL) {
901 if (strcmp(arg, "-batch") == 0)
902 SetSymbolValue(BATCH_MODE, T);
907 SetSymbolValue(UNIDATA_PATH, alloc_string(unidata));
912 * Pick off sigint until the lisp system gets far enough along to
917 #ifdef DEBUG_BAD_HEAP
919 * At this point, there should be exactly 4 objects in static
920 * space pointing to apparently free pages. These 4 objects were
921 * just created above for *lisp-command-line-list*,
922 * *lisp-environment-list*, *cmucl-lib*, and *cmucl-core-path*.
927 #if defined(__linux__)
929 * On newer (?) versions of Linux, tzset appears to call malloc.
930 * We set up the timezone here so that malloc happens as late as
941 funcall0(initial_function);
942 printf("Initial function returned?\n");
945 return 0; /* not reached */