diff --git a/pkgs/racket-doc/scribblings/reference/startup.scrbl b/pkgs/racket-doc/scribblings/reference/startup.scrbl index 063fc18454..740189678f 100644 --- a/pkgs/racket-doc/scribblings/reference/startup.scrbl +++ b/pkgs/racket-doc/scribblings/reference/startup.scrbl @@ -195,7 +195,9 @@ flags: @nonterm{m} and from @nonterm{m} to @nonterm{p}. (On Mac OS, @nonterm{n}, @nonterm{m}, and @nonterm{p} are relative to a @tt{__PLTSCHEME} segment in the executable. On Windows, - they are relative to a resource of type 257 and ID 1.) The first range + they are relative to a resource of type 257 and ID 1. On Unix + using ELF, they are relative to the @tt{.rackprog} segment + in the executable.) The first range is loaded in every new @tech{place}, and any modules declared in that range are considered predefined in the sense of @racket[module-predefined?]. This option is normally embedded @@ -203,7 +205,7 @@ flags: @item{@FlagFirst{Y} @nonterm{file} @nonterm{n} @nonterm{m} @nonterm{p} : Like @Flag{k} @nonterm{n} @nonterm{m} @nonterm{p}, but reading - from @nonterm{file} (without any adjustment on Mac OS or Windows + from @nonterm{file} (without any adjustment for a segment or resource offset).} @item{@FlagFirst{m} or @DFlagFirst{main} : Evaluates a call to diff --git a/racket/collects/compiler/embed.rkt b/racket/collects/compiler/embed.rkt index 954e9dfff9..b1aa836aad 100644 --- a/racket/collects/compiler/embed.rkt +++ b/racket/collects/compiler/embed.rkt @@ -1511,9 +1511,7 @@ (let ([m (assq 'original-exe? aux)]) (or (not m) (not (cdr m)))))) - (define long-cmdline? (or (eq? (cross-system-type) 'windows) - (eq? (cross-system-type) 'macosx) - unix-starter?)) + (define long-cmdline? #t) (define relative? (let ([m (assq 'relative? aux)]) (and m (cdr m)))) (define collects-path-bytes (collects-path->bytes @@ -1762,15 +1760,18 @@ new-rsrcs)) (update-resources dest-exe pe new+dll-rsrcs) (values 0 decl-len init-len (+ init-len cmdline-len))] - [(and (eq? (cross-system-type) 'macosx) - (not unix-starter?)) + [(memq (cross-system-type 'os*) '(macosx darwin)) ;; For Mach-O, we know how to add a proper segment + (remove-signature dest-exe) ; may be needed in 'darwin mode (define s (open-output-bytes)) (define decl-len (write-module s)) (let* ([s (get-output-bytes s)] [cl (let ([o (open-output-bytes)]) ;; position is relative to __PLTSCHEME: - (write-cmdline (make-full-cmdline 0 decl-len (bytes-length s)) o) + (let ([cmdline (make-full-cmdline 0 decl-len (bytes-length s))]) + (cond + [unix-starter? (display (make-starter-cmdline cmdline) o)] + [else (write-cmdline cmdline o)])) (get-output-bytes o))]) (let ([start (add-plt-segment dest-exe @@ -1783,28 +1784,25 @@ (+ start (bytes-length s)) (+ start (bytes-length s) (bytes-length cl))))))] [else - ;; Unix starter: Maybe ELF, in which case we + ;; Unix starter or direct embedding: Maybe ELF, in which case we ;; can add a proper section (define-values (s e dl p) - (if unix-starter? - (add-racket-section - orig-exe - dest-exe - (if launcher? #".rackcmdl" #".rackprog") - (lambda (start) - (let ([s (open-output-bytes)]) - (define decl-len (write-module s)) - (let ([p (file-position s)]) - (display (make-starter-cmdline - (make-full-cmdline start - (+ start decl-len) - (+ start p))) - s) - (values (get-output-bytes s) decl-len p))))) - (values #f #f #f #f))) + (add-racket-section + orig-exe + dest-exe + #".rackprog" + (lambda (start) + (let ([s (open-output-bytes)]) + (define decl-len (write-module s)) + (let ([p (file-position s)]) + (let ([cmdline (make-full-cmdline 0 decl-len p)]) + (cond + [unix-starter? (display (make-starter-cmdline cmdline) s)] + [else (write-cmdline cmdline s)])) + (values (get-output-bytes s) decl-len p)))))) (if (and s e) - ;; ELF succeeded: - (values s (+ s dl) (+ s p) e) + ;; ELF succeeded, so make values relative to start: + (values 0 dl p (- e s)) ;; Otherwise, just add to the end of the file: (let ([start (file-size dest-exe)]) (define decl-end @@ -1849,11 +1847,11 @@ "exeuctable type" #"bINARy tYPe:"))))] [cmdline (if cmdline-end - #f - (make-starter-cmdline full-cmdline))] + #f + (make-starter-cmdline full-cmdline))] [out (open-output-file dest-exe #:exists 'update)]) (let ([old-cmdline-end cmdline-end] - [cmdline-end (or cmdline-end (+ end (bytes-length cmdline)))] + [cmdline-end (or cmdline-end (+ end (bytes-length cmdline)))] [write-num (lambda (n) (write-bytes (integer->integer-bytes n 4 #t #f) out))]) (dynamic-wind @@ -1879,10 +1877,10 @@ (write-num (length full-cmdline)) (write-num (if mred? 1 0)) (flush-output out) - (unless old-cmdline-end - (file-position out end) - (write-bytes cmdline out) - (flush-output out))) + (unless old-cmdline-end + (file-position out end) + (write-bytes cmdline out) + (flush-output out))) (lambda () (close-output-port out)))))] [else @@ -1936,7 +1934,7 @@ (assq 'subsystem aux))]) (when m (set-subsystem dest-exe (cdr m)))))])))) - (when (eq? (cross-system-type) 'macosx) + (when (memq (cross-system-type 'os*) '(macosx darwin)) (add-ad-hoc-signature dest-exe)) (done-writable dest-exe old-perms)))))) diff --git a/racket/collects/ffi/unsafe/nsalloc.rkt b/racket/collects/ffi/unsafe/nsalloc.rkt index 496984ac88..d1379866eb 100644 --- a/racket/collects/ffi/unsafe/nsalloc.rkt +++ b/racket/collects/ffi/unsafe/nsalloc.rkt @@ -7,9 +7,10 @@ call-with-autorelease)) ;; Make sure Foundation is loaded: -(when (eq? 'macosx (system-type)) - (void (ffi-lib "/System/Library/Frameworks/Foundation.framework/Foundation" - #:fail (lambda () #f)))) +(case (system-type 'os*) + [(macosx darwin) + (void (ffi-lib "/System/Library/Frameworks/Foundation.framework/Foundation" + #:fail (lambda () #f)))]) (import-class NSAutoreleasePool) diff --git a/racket/collects/net/osx-ssl.rkt b/racket/collects/net/osx-ssl.rkt index 6a5029a7cf..8e9f903035 100644 --- a/racket/collects/net/osx-ssl.rkt +++ b/racket/collects/net/osx-ssl.rkt @@ -17,16 +17,19 @@ osx-old-openssl?) (define (osx-old-openssl?) - (and (eq? 'macosx (system-type)) + (and (or (eq? 'macosx (system-type)) + (eq? 'darwin (system-type 'os*))) (not (eq? 'ppc (system-type 'arch))) ; Mac OS 10.5 is too old for this to work? (or (not ssl-available?) (not (memq 'tls12 (supported-client-protocols)))))) (define cf-lib - (and (eq? 'macosx (system-type)) + (and (or (eq? 'macosx (system-type)) + (eq? 'darwin (system-type 'os*))) (ffi-lib "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation"))) (define net-lib - (and (eq? 'macosx (system-type)) + (and (or (eq? 'macosx (system-type)) + (eq? 'darwin (system-type 'os*))) (ffi-lib "/System/Library/Frameworks/CFNetwork.framework/CFNetwork" #:fail (lambda () diff --git a/racket/collects/openssl/mzssl.rkt b/racket/collects/openssl/mzssl.rkt index b824a414cf..703d158f0b 100644 --- a/racket/collects/openssl/mzssl.rkt +++ b/racket/collects/openssl/mzssl.rkt @@ -479,12 +479,12 @@ TO DO: (define ssl-default-verify-sources (make-parameter - (case (system-type) + (case (system-type 'os*) [(windows) ;; On Windows, x509-root-sources produces paths like "/usr/local/ssl/certs", which ;; aren't useful. So just skip them. '((win32-store "ROOT"))] - [(macosx) + [(macosx darwin) '((macosx-keychain "/System/Library/Keychains/SystemRootCertificates.keychain"))] [else (x509-root-sources)]))) diff --git a/racket/collects/openssl/private/macosx.rkt b/racket/collects/openssl/private/macosx.rkt index 126c578a6c..d67c4dcdd1 100644 --- a/racket/collects/openssl/private/macosx.rkt +++ b/racket/collects/openssl/private/macosx.rkt @@ -16,8 +16,8 @@ ;; security export -k /System/Library/Keychains/... -t certs -f pemseq -o foo.pem (define libcf - (case (system-type) - [(macosx) (ffi-lib "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")] + (case (system-type 'os*) + [(macosx darwin) (ffi-lib "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")] [else #f])) (define-ffi-definer define-cf libcf @@ -47,8 +47,8 @@ ;; ---- (define libsec - (case (system-type) - [(macosx) (ffi-lib "/System/Library/Frameworks/Security.framework/Security")] + (case (system-type 'os*) + [(macosx darwin) (ffi-lib "/System/Library/Frameworks/Security.framework/Security")] [else #f])) (define-ffi-definer define-sec libsec #:default-make-fail make-not-available) diff --git a/racket/src/bc/Makefile.in b/racket/src/bc/Makefile.in index 985f54e934..3393e0c55e 100644 --- a/racket/src/bc/Makefile.in +++ b/racket/src/bc/Makefile.in @@ -304,7 +304,7 @@ DEF_C_DIRS = $(DEF_COLLECTS_DIR) $(DEF_CONFIG_DIR) MAIN_HEADER_DEPS = $(srcdir)/include/scheme.h $(srcdir)/include/schthread.h $(srcdir)/sconfig.h \ $(srcdir)/src/stypes.h $(srcdir)/cmdline.inc $(srcdir)/../start/parse_cmdl.inc \ $(srcdir)/../start/cmdl_to_argv.inc \ - $(srcdir)/../start/config.inc $(srcdir)/../start/delayed.inc \ + $(srcdir)/../start/config.inc $(srcdir)/../start/self_exe.inc $(srcdir)/../start/delayed.inc \ $(srcdir)/../start/embedded_dll.inc MAIN_INCLUDES = -I$(builddir) -I$(srcdir)/include -I$(srcdir)/../version @@ -499,6 +499,7 @@ unix-install-cgc: cd ..; $(STRIP_DEBUG) "$(DESTDIR)$(bindir)/racket@CGC_INSTALLED@" cd ..; cp bc/mzdyn.o "$(DESTDIR)$(libpltdir)/mzdyn.o" @RUN_RACKET_CGC@ $(SETUP_BOOT_COLLECTS_PATH) "$(DESTDIR)$(bindir)/racket@CGC_INSTALLED@@EXE_SUFFIX@" $(DESTDIR)@COLLECTS_PATH@ $(DESTDIR)@CONFIG_PATH@ + $(RESTORE_SIGNATURE) "$(DESTDIR)$(bindir)/racket@CGC_INSTALLED@" unix-install-libs-cgc: cd ..; $(ICP_LIB) bc/libmzgc.@LIBSFX@ "$(DESTDIR)$(libdir)/libmzgc.@LIBSFX@" @@ -520,6 +521,7 @@ unix-install-3m: $(MAKE) unix-@INSTALL_LIBS_ENABLE@-libs-3m cd ..; $(ICP) bc/mzdyn3m.o "$(DESTDIR)$(libpltdir)/mzdyn3m.o" @RUN_RACKET_MMM@ $(SETUP_BOOT_COLLECTS_PATH) "$(DESTDIR)$(bindir)/racket@MMM_INSTALLED@@EXE_SUFFIX@" $(DESTDIR)@COLLECTS_PATH@ $(DESTDIR)@CONFIG_PATH@ + $(RESTORE_SIGNATURE) "$(DESTDIR)$(bindir)/racket@MMM_INSTALLED@" unix-install-libs-3m: cd ..; $(ICP_LIB) bc/libracket3m.@LIBSFX@ "$(DESTDIR)$(libdir)/libracket3m.@LIBSFX@" @@ -604,6 +606,7 @@ osx-install-cgc: $(MAKE) unix-install-cgc mkdir -p $(DESTDIR)$(MZFWDIR)/Versions/$(FWVERSION) cp $(MZFW) $(DESTDIR)$(MZFWDIR)/Versions/$(FWVERSION)/ + $(STRIP_SIGNATURE) $(DESTDIR)"$(bindir)/racket@CGC_INSTALLED@" /usr/bin/install_name_tool -change "@executable_path/Racket.framework/Versions/$(FWVERSION)/Racket" "@FRAMEWORK_PREFIX@Racket.framework/Versions/$(FWVERSION)/Racket" $(DESTDIR)"$(bindir)/racket@CGC_INSTALLED@" $(RESTORE_SIGNATURE) $(DESTDIR)"$(bindir)/racket@CGC_INSTALLED@" @@ -615,6 +618,7 @@ osx-install-3m: $(MAKE) unix-install-3m mkdir -p $(DESTDIR)"$(MZFWDIR)/Versions/$(FWVERSION)_3m" cp $(MZFWMMM) $(DESTDIR)$(MZFWDIR)/Versions/$(FWVERSION)_3m/ + $(STRIP_SIGNATURE) $(DESTDIR)"$(bindir)/racket@MMM_INSTALLED@" /usr/bin/install_name_tool -change "@executable_path/Racket.framework/Versions/$(FWVERSION)_3m/Racket" "@FRAMEWORK_PREFIX@Racket.framework/Versions/$(FWVERSION)_3m/Racket" $(DESTDIR)"$(bindir)/racket@MMM_INSTALLED@" $(RESTORE_SIGNATURE) $(DESTDIR)"$(bindir)/racket@MMM_INSTALLED@" diff --git a/racket/src/bc/cmdline.inc b/racket/src/bc/cmdline.inc index 4274b8d889..81bb27d936 100644 --- a/racket/src/bc/cmdline.inc +++ b/racket/src/bc/cmdline.inc @@ -42,7 +42,6 @@ static int is_number_arg(const char *s) return 1; } -#if defined(OS_X) || defined(DOS_FILE_SYSTEM) char *add_to_str(const char *addr, long amt) { long addr_v; @@ -51,23 +50,19 @@ char *add_to_str(const char *addr, long amt) sprintf(buf, "%ld", addr_v); return strdup(buf); } -#endif -static char *make_embedded_load(const char *file, const char *start, const char *end) +static char *make_embedded_load(const self_exe_t self_exe, const char *file, const char *start, const char *end) { char *s; int slen, elen, flen; -#if defined(OS_X) || defined(DOS_FILE_SYSTEM) if (file == NULL) { long fileoff; - fileoff = get_segment_offset(); + fileoff = get_segment_offset(self_exe); start = add_to_str(start, fileoff); end = add_to_str(end, fileoff); + file = SELF_PATH_TO_BYTES(self_exe); } -#endif - - if (!file) file = ""; slen = strlen(start); elen = strlen(end); @@ -730,6 +725,7 @@ static int run_from_cmd_line(int argc, char *_argv[], Scheme_Object *syslog_level = NULL, *stderr_level = NULL, *stdout_level = NULL; FinishArgs *fa; FinishArgsAtoms *fa_a; + self_exe_t self_exe; scheme_set_default_locale(); @@ -740,8 +736,10 @@ static int run_from_cmd_line(int argc, char *_argv[], #ifdef NEED_CONSOLE_PRINTF console_printf = scheme_get_console_printf(); #endif - - extract_built_in_arguments(&prog, &sprog, &argc, &argv); + + self_exe = get_self_path(prog); + + extract_built_in_arguments(self_exe, &prog, &sprog, &argc, &argv); #ifndef DONT_PARSE_COMMAND_LINE evals_and_loads = (char **)malloc(sizeof(char *) * argc); @@ -1024,12 +1022,12 @@ static int run_from_cmd_line(int argc, char *_argv[], } argv++; --argc; - se = make_embedded_load(embedding_file, argv[0], argv[1]); + se = make_embedded_load(self_exe, embedding_file, argv[0], argv[1]); evals_and_loads[num_enl] = se; argv++; --argc; eval_kind[num_enl++] = mzcmd_EMBEDDED_REG; - se = make_embedded_load(embedding_file, argv[0], argv[1]); + se = make_embedded_load(self_exe, embedding_file, argv[0], argv[1]); evals_and_loads[num_enl] = se; argv++; --argc; diff --git a/racket/src/bc/dynsrc/Makefile.in b/racket/src/bc/dynsrc/Makefile.in index 13d63d1c6a..771f13149e 100644 --- a/racket/src/bc/dynsrc/Makefile.in +++ b/racket/src/bc/dynsrc/Makefile.in @@ -60,7 +60,7 @@ MZDYNDEP = ../mzdyn.o $(srcdir)/../include/ext.exp $(srcdir)/../include/racket.e dynexmpl.o: $(srcdir)/dynexmpl.c $(HEADERS) $(PLAIN_CC) $(ALL_CFLAGS) -c $(srcdir)/dynexmpl.c -o dynexmpl.o -../starter@NOT_MINGW@@EXE_SUFFIX@: $(srcdir)/../../start/ustart.c $(srcdir)/../../start/unix_self.inc +../starter@NOT_MINGW@@EXE_SUFFIX@: $(srcdir)/../../start/ustart.c $(srcdir)/../../start/self_exe.inc $(PLAIN_CC) $(ALL_CFLAGS) -o ../starter@EXE_SUFFIX@ $(srcdir)/../../start/ustart.c PARSE_CMDL = $(srcdir)/../../start/parse_cmdl.inc diff --git a/racket/src/bc/gracket/Makefile.in b/racket/src/bc/gracket/Makefile.in index 0b63a5f92b..b89a975309 100644 --- a/racket/src/bc/gracket/Makefile.in +++ b/racket/src/bc/gracket/Makefile.in @@ -57,6 +57,9 @@ LDFLAGS = @LDFLAGS@ ARLIBFLAGS = $(LDFLAGS) $(LDLIBS) ########################### +STRIP_SIGNATURE = @STRIP_SIGNATURE@ +RESTORE_SIGNATURE = @RESTORE_SIGNATURE@ "${srcdir}/../../mac/entitlements.plist" + GRACKETLINKER = @MZLINKER@ LIBRKTIO = ../rktio/librktio.@LTA@ @@ -224,8 +227,10 @@ GRACKET_NAME@MINGW@ = GRacket install-wx_xt-cgc: $(MAKE) @MRLIBINSTALL@-cgc-wx_xt cd ..; $(ICP) gracket/gracket@CGC@@EXE_SUFFIX@ "$(DESTDIR)$(libpltdir)/$(GRACKET_NAME)@CGC_INSTALLED@@EXE_SUFFIX@" + $(STRIP_SIGNATURE) "$(DESTDIR)$(libpltdir)/$(GRACKET_NAME)@CGC_INSTALLED@@EXE_SUFFIX@" cd ..; @STRIP_DEBUG@ "$(DESTDIR)$(libpltdir)/$(GRACKET_NAME)@CGC_INSTALLED@@EXE_SUFFIX@" @RUN_RACKET_CGC@ $(SETUP_BOOT_COLLECTS_PATH) @DIRCVTPRE@"$(DESTDIR)$(libpltdir)/$(GRACKET_NAME)@CGC_INSTALLED@@EXE_SUFFIX@"@DIRCVTPOST@ @GUI_COLLECTS_PATH@ @GUI_CONFIG_PATH@ + $(RESTORE_SIGNATURE) "$(DESTDIR)$(libpltdir)/$(GRACKET_NAME)@CGC_INSTALLED@@EXE_SUFFIX@" install-wx_xt-cgc-final: $(NOOP) @@ -239,8 +244,10 @@ install-lib-3m-wx_xt: install-wx_xt-3m: $(MAKE) @MRLIBINSTALL@-3m-wx_xt cd ..; $(ICP) gracket/gracket@MMM@@EXE_SUFFIX@ "$(DESTDIR)$(libpltdir)/$(GRACKET_NAME)@MMM_INSTALLED@@EXE_SUFFIX@" + $(STRIP_SIGNATURE) "$(DESTDIR)$(libpltdir)/$(GRACKET_NAME)@MMM_INSTALLED@@EXE_SUFFIX@" cd ..; @STRIP_DEBUG@ "$(DESTDIR)$(libpltdir)/$(GRACKET_NAME)@MMM_INSTALLED@@EXE_SUFFIX@" @RUN_RACKET_MMM@ $(SETUP_BOOT_COLLECTS_PATH) @DIRCVTPRE@"$(DESTDIR)$(libpltdir)/$(GRACKET_NAME)@MMM_INSTALLED@@EXE_SUFFIX@"@DIRCVTPOST@ @GUI_COLLECTS_PATH@ @GUI_CONFIG_PATH@ + $(RESTORE_SIGNATURE) "$(DESTDIR)$(libpltdir)/$(GRACKET_NAME)@MMM_INSTALLED@@EXE_SUFFIX@" install-wx_xt-3m-final: $(NOOP) diff --git a/racket/src/cs/Makefile b/racket/src/cs/Makefile index 6b8f0e98ea..aa54535413 100644 --- a/racket/src/cs/Makefile +++ b/racket/src/cs/Makefile @@ -32,7 +32,7 @@ EXTRA_COMPILE_DEPS = COMPILE_FILE = $(SCHEME) --script compile-file.ss $(UNSAFE_COMP) $(COMPRESS_COMP) $(DEBUG_COMP) $(CROSS_COMP) --dest "$(BUILDDIR)" COMPILE_FILE_DEPS = compile-file.ss include.ss place-register.ss $(EXTRA_COMPILE_DEPS) -RACKET_SETUP_ARGS = false ../../bin/racket ../../bin/racket ../collects ../etc 0 false false 0 "" +RACKET_SETUP_ARGS = false ../../bin/racket ../../bin/racket ../collects ../etc "" 0 false false 0 "" PRIMITIVES_TABLES = primitive/kernel.ss primitive/unsafe.ss primitive/flfxnum.ss \ primitive/paramz.ss primitive/extfl.ss primitive/network.ss \ diff --git a/racket/src/cs/c/Makefile.in b/racket/src/cs/c/Makefile.in index f223a00ac9..262c920ff8 100644 --- a/racket/src/cs/c/Makefile.in +++ b/racket/src/cs/c/Makefile.in @@ -212,12 +212,12 @@ racket.boot: racket.so EMBED_DEPS = $(srcdir)/embed-boot.rkt racketcs@NOT_OSX@@NOT_MINGW@: raw_racketcs petite-v.boot scheme-v.boot racket-v.boot $(EMBED_DEPS) - $(BOOTSTRAP_RACKET) $(srcdir)/embed-boot.rkt @ELF_COMP@ --target $(TARGET_MACH) @BOOT_COMPRESS_COMP@ raw_racketcs racketcs petite-v.boot scheme-v.boot racket-v.boot + $(BOOTSTRAP_RACKET) $(srcdir)/embed-boot.rkt --target $(TARGET_MACH) @BOOT_COMPRESS_COMP@ raw_racketcs racketcs petite-v.boot scheme-v.boot racket-v.boot @POST_LINKER@ racketcs $(RESTORE_SIGNATURE) racketcs gracketcs@NOT_OSX@@NOT_MINGW@: raw_gracketcs petite-v.boot scheme-v.boot racket-v.boot $(EMBED_DEPS) - $(BOOTSTRAP_RACKET) $(srcdir)/embed-boot.rkt @ELF_COMP@ --target $(TARGET_MACH) @BOOT_COMPRESS_COMP@ raw_gracketcs gracketcs petite-v.boot scheme-v.boot racket-v.boot + $(BOOTSTRAP_RACKET) $(srcdir)/embed-boot.rkt --target $(TARGET_MACH) @BOOT_COMPRESS_COMP@ raw_gracketcs gracketcs petite-v.boot scheme-v.boot racket-v.boot @POST_LINKER@ gracketcs $(RESTORE_SIGNATURE) gracketcs @@ -433,7 +433,7 @@ DEF_C_DIRS = $(DEF_COLLECTS_DIR) $(DEF_CONFIG_DIR) MAIN_DEPS = $(srcdir)/main.c $(srcdir)/boot.h cs_config.h \ $(srcdir)/../../start/config.inc \ - $(srcdir)/../../start/unix_self.inc + $(srcdir)/../../start/self_exe.inc main.o: $(MAIN_DEPS) $(CC) $(CFLAGS) $(DEF_C_DIRS) -c -o main.o $(srcdir)/main.c @@ -444,7 +444,7 @@ grmain.o: $(srcdir)/grmain.c $(MAIN_DEPS) $(srcdir)/../../start/gui_filter.inc boot.o: $(srcdir)/boot.c $(srcdir)/../../rktio/rktio.inc $(srcdir)/boot.h $(CC) $(CFLAGS) -c -o boot.o $(srcdir)/boot.c -starter@NOT_MINGW@: $(srcdir)/../../start/ustart.c $(srcdir)/../../start/unix_self.inc +starter@NOT_MINGW@: $(srcdir)/../../start/ustart.c $(srcdir)/../../start/self_exe.inc $(CC) $(CFLAGS) -o starter $(srcdir)/../../start/ustart.c diff --git a/racket/src/cs/c/boot.c b/racket/src/cs/c/boot.c index 13aa0b8e50..5d7c98a712 100644 --- a/racket/src/cs/c/boot.c +++ b/racket/src/cs/c/boot.c @@ -192,9 +192,10 @@ void racket_boot(racket_boot_arguments_t *ba) l = Scons(Sbytevector(ba->cs_compiled_subdir ? "true" : "false"), l); sprintf(segment_offset_s, "%ld", ba->segment_offset); l = Scons(Sbytevector(segment_offset_s), l); + l = Scons(Sbytevector(ba->k_file ? (char *)ba->k_file : (char *)ba->exec_file), l); l = Scons(Sbytevector(ba->config_dir ? (char *)ba->config_dir : "etc"), l); l = Scons(parse_coldirs(ba->collects_dir ? (char *)ba->collects_dir : ""), l); - l = Scons(Sbytevector(ba->run_file ? (char *)ba->run_file : (char *)ba->exec_file ), l); + l = Scons(Sbytevector(ba->run_file ? (char *)ba->run_file : (char *)ba->exec_file), l); l = Scons(Sbytevector((char *)ba->exec_file), l); l = Scons(Sbytevector(ba->exit_after ? "false" : "true"), l); diff --git a/racket/src/cs/c/boot.h b/racket/src/cs/c/boot.h index f9560ba94c..e7af14110a 100644 --- a/racket/src/cs/c/boot.h +++ b/racket/src/cs/c/boot.h @@ -30,6 +30,7 @@ typedef struct racket_boot_arguments_t { const char *collects_dir; /* can be NULL or "" to disable collection path */ const char *config_dir; /* use NULL or "etc" if you don't care */ /* wchar_t * */void *dll_dir; /* can be NULL for default */ + const char *k_file; /* for -k; can be NULL for the same as `exec_file` */ /* How to initialize `use-compiled-file-paths`: */ int cs_compiled_subdir; /* true => subdirectory of "compiled" */ diff --git a/racket/src/cs/c/configure b/racket/src/cs/c/configure index 6178369e41..57a598ac78 100755 --- a/racket/src/cs/c/configure +++ b/racket/src/cs/c/configure @@ -639,7 +639,6 @@ FRAMEWORK_INSTALL_DIR SCHEME_CROSS_CONFIG_ARGS SCHEME_CONFIG_ARGS MAKE_BUILD_SCHEME -ELF_COMP BOOT_COMPRESS_COMP COMPRESS_COMP CONFIGURE_RACKET_SO_COMPILE @@ -3222,7 +3221,6 @@ NOT_MINGW="" CONFIGURE_RACKET_SO_COMPILE="" COMPRESS_COMP="" BOOT_COMPRESS_COMP="" -ELF_COMP="" POST_LINKER="echo" FRAMEWORK_INSTALL_DIR='$(libpltdir)' @@ -4336,7 +4334,6 @@ case "$host_os" in LIBS="$LIBS -lsocket -lnsl -lintl" use_flag_pthread="no" use_flag_posix_pthread="yes" - enable_strip=no ;; aix*) ;; @@ -4347,8 +4344,6 @@ case "$host_os" in LIBS="${LIBS} -lm -lpthread" LINK_DYNAMIC="-rdynamic" add_iconv_lib="-liconv" - CPPFLAGS="${CPPFLAGS} -DELF_FIND_BOOT_SECTION" - ELF_COMP="--expect-elf" ;; openbsd*) MACH_OS=ob @@ -4358,8 +4353,6 @@ case "$host_os" in LINK_DYNAMIC="-Wl,--export-dynamic" add_iconv_lib="-liconv" LDFLAGS="${LDFLAGS} -Wl,-zwxneeded" - CPPFLAGS="${CPPFLAGS} -DELF_FIND_BOOT_SECTION" - ELF_COMP="--expect-elf" ;; bitrig*) LINK_DYNAMIC="-Wl,--export-dynamic" @@ -4372,8 +4365,6 @@ case "$host_os" in LIBS="${LIBS} -lm -lpthread" LINK_DYNAMIC="-rdynamic" add_iconv_lib="/usr/lib/i18n/libiconv_std.a" - CPPFLAGS="${CPPFLAGS} -DELF_FIND_BOOT_SECTION" - ELF_COMP="--expect-elf" POST_LINKER="paxctl +m" ;; irix*) @@ -4387,9 +4378,7 @@ case "$host_os" in LIBS="${LIBS} -lrt" ;; esac - CPPFLAGS="${CPPFLAGS} -DELF_FIND_BOOT_SECTION" LINK_DYNAMIC="-rdynamic" - ELF_COMP="--expect-elf" ;; osf1*) ;; @@ -5793,7 +5782,6 @@ SCHEME_CROSS_CONFIG_ARGS="--machine=${TARGET_MACH} --disable-x11 ${cs_auto_flags - makefiles="Makefile" diff --git a/racket/src/cs/c/configure.ac b/racket/src/cs/c/configure.ac index c5299fc1ed..b29cacf941 100644 --- a/racket/src/cs/c/configure.ac +++ b/racket/src/cs/c/configure.ac @@ -140,7 +140,6 @@ NOT_MINGW="" CONFIGURE_RACKET_SO_COMPILE="" COMPRESS_COMP="" BOOT_COMPRESS_COMP="" -ELF_COMP="" POST_LINKER="echo" FRAMEWORK_INSTALL_DIR='$(libpltdir)' @@ -218,7 +217,6 @@ case "$host_os" in LIBS="$LIBS -lsocket -lnsl -lintl" use_flag_pthread="no" use_flag_posix_pthread="yes" - enable_strip=no ;; aix*) ;; @@ -229,8 +227,6 @@ case "$host_os" in LIBS="${LIBS} -lm -lpthread" LINK_DYNAMIC="-rdynamic" add_iconv_lib="-liconv" - CPPFLAGS="${CPPFLAGS} -DELF_FIND_BOOT_SECTION" - ELF_COMP="--expect-elf" ;; openbsd*) MACH_OS=ob @@ -240,8 +236,6 @@ case "$host_os" in LINK_DYNAMIC="-Wl,--export-dynamic" add_iconv_lib="-liconv" LDFLAGS="${LDFLAGS} -Wl,-zwxneeded" - CPPFLAGS="${CPPFLAGS} -DELF_FIND_BOOT_SECTION" - ELF_COMP="--expect-elf" ;; bitrig*) LINK_DYNAMIC="-Wl,--export-dynamic" @@ -254,8 +248,6 @@ case "$host_os" in LIBS="${LIBS} -lm -lpthread" LINK_DYNAMIC="-rdynamic" add_iconv_lib="/usr/lib/i18n/libiconv_std.a" - CPPFLAGS="${CPPFLAGS} -DELF_FIND_BOOT_SECTION" - ELF_COMP="--expect-elf" POST_LINKER="paxctl +m" ;; irix*) @@ -269,9 +261,7 @@ case "$host_os" in LIBS="${LIBS} -lrt" ;; esac - CPPFLAGS="${CPPFLAGS} -DELF_FIND_BOOT_SECTION" LINK_DYNAMIC="-rdynamic" - ELF_COMP="--expect-elf" ;; osf1*) ;; @@ -819,7 +809,6 @@ AC_SUBST(LZ4_LIB_UNPACK) AC_SUBST(CONFIGURE_RACKET_SO_COMPILE) AC_SUBST(COMPRESS_COMP) AC_SUBST(BOOT_COMPRESS_COMP) -AC_SUBST(ELF_COMP) AC_SUBST(MAKE_BUILD_SCHEME) AC_SUBST(SCHEME_CONFIG_ARGS) AC_SUBST(SCHEME_CROSS_CONFIG_ARGS) diff --git a/racket/src/cs/c/embed-boot.rkt b/racket/src/cs/c/embed-boot.rkt index e6c8d71e4d..f9093576d1 100644 --- a/racket/src/cs/c/embed-boot.rkt +++ b/racket/src/cs/c/embed-boot.rkt @@ -6,7 +6,6 @@ compiler/private/elf "adjust-compress.rkt") -(define expect-elf? #f) (define alt-dests '()) (define target #f) @@ -14,8 +13,6 @@ #:once-each [("--compress") "Leave compiled code files as compressed" (enable-compress!)] - [("--expect-elf") "Record offset from ELF section" - (set! expect-elf? #t)] [("--target") machine "Select target machine" (set! target machine)] #:multi @@ -57,7 +54,10 @@ "x86_64-darwin" "i386-darwin" "aarch64-darwin" "x86_64-macosx" "i386-macosx" "aarch64-macosx") ;; Mach-O - (copy-file use-src-file dest-file #t) + (when (file-exists? dest-file) + ;; explicit delete to avoid signature unhappiness + (delete-file dest-file)) + (copy-file use-src-file dest-file) (remove-signature dest-file) (add-plt-segment dest-file data #:name #"__RKTBOOT") ;; Find segment at run time: @@ -86,12 +86,8 @@ [start-pos ;; Success as ELF (file-or-directory-permissions dest-file (file-or-directory-permissions use-src-file 'bits)) - (cond - [expect-elf? - ;; Find ".rackboot" at run time: - 0] - [else - start-pos])] + ;; Find ".rackboot" at run time: + 0] [else ;; Not ELF; just append to the end (copy-file use-src-file dest-file #t) @@ -102,8 +98,6 @@ (lambda (o) (file-position o pos) (write-bytes data o))) - (when expect-elf? - (error 'embed-boot "expected ELF")) pos])])) (define (write-offsets dest-file) diff --git a/racket/src/cs/c/main.c b/racket/src/cs/c/main.c index c8457a4e8a..47dec88c21 100644 --- a/racket/src/cs/c/main.c +++ b/racket/src/cs/c/main.c @@ -57,34 +57,11 @@ PRESERVE_IN_EXECUTABLE char *boot_file_data = "BooT FilE OffsetS:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; static int boot_file_offset = 18; -#include "../../start/unix_self.inc" - #ifdef OS_X # include static long find_rktboot_section(char *me) { - const struct mach_header *mh; - const struct load_command *lc; - int i; - - mh = _dyld_get_image_header(0); - - lc = (void *)((char *)mh + ((mh->magic == 0xfeedfacf) ? sizeof(struct mach_header_64) : sizeof(struct mach_header))); - - for (i = 0; i < mh->ncmds; i++) { - if (lc->cmd == LC_SEGMENT) { - const struct segment_command *sc = (struct segment_command *)lc; - if (!strcmp(sc->segname, "__RKTBOOT")) - return sc->fileoff; - } else if (lc->cmd == LC_SEGMENT_64) { - const struct segment_command_64 *sc = (struct segment_command_64 *)lc; - if (!strcmp(sc->segname, "__RKTBOOT")) - return sc->fileoff; - } - lc = (void *)((char *)lc + lc->cmdsize); - } - - return 0; + return find_mach_o_segment("__RKTBOOT", NULL); } #endif @@ -127,69 +104,18 @@ static char *path_append(const char *p1, char *p2) { #endif -#ifdef ELF_FIND_BOOT_SECTION -# include -# include - -static long find_boot_section(char *me) +#if !defined(WIN32) && !defined(OS_X) +static long find_boot_section(const char *me) { - int fd, i; -#if SIZEOF_VOID_P == 4 - Elf32_Ehdr e; - Elf32_Shdr s; -#else - Elf64_Ehdr e; - Elf64_Shdr s; -#endif - char *strs; + int start = 0, end = 0; + + find_elf_section_offset(me, ".rackboot", &start, &end); - fd = open(me, O_RDONLY, 0); - if (fd == -1) return 0; - - if (read(fd, &e, sizeof(e)) == sizeof(e)) { - lseek(fd, e.e_shoff + (e.e_shstrndx * e.e_shentsize), SEEK_SET); - if (read(fd, &s, sizeof(s)) != sizeof(s)) { - close(fd); - return 0; - } - - strs = (char *)malloc(s.sh_size); - lseek(fd, s.sh_offset, SEEK_SET); - if (read(fd, strs, s.sh_size) != s.sh_size) { - close(fd); - return 0; - } - - for (i = 0; i < e.e_shnum; i++) { - lseek(fd, e.e_shoff + (i * e.e_shentsize), SEEK_SET); - if (read(fd, &s, sizeof(s)) != sizeof(s)) { - close(fd); - return 0; - } - if (!strcmp(strs + s.sh_name, ".rackboot")) { - close(fd); - return s.sh_offset; - } - } - } - - close(fd); - return 0; + return start; } #endif #ifdef WIN32 -static char *string_to_utf8(wchar_t *p) -{ - char *r; - int len; - - len = WideCharToMultiByte(CP_UTF8, 0, p, -1, NULL, 0, NULL, NULL); - r = malloc(len); - len = WideCharToMultiByte(CP_UTF8, 0, p, -1, r, len, NULL, NULL); - - return r; -} static int scheme_utf8_encode(unsigned int *path, int zero_offset, int len, char *dest, int offset, int get_utf16) @@ -202,126 +128,6 @@ static int scheme_utf8_encode(unsigned int *path, int zero_offset, int len, } # include "../start/cmdl_to_argv.inc" - -# undef USE_GENERIC_GET_SELF_PATH -#endif - -#ifdef USE_GENERIC_GET_SELF_PATH -/* Get executable path via argv[0] and the `PATH` environment variable */ - -static int has_slash(char *s) -{ - while (*s) { - if (s[0] == '/') - return 1; - s++; - } - return 0; -} - -static char *do_path_append(char *s1, int l1, char *s2) -{ - int l2; - char *s; - - l2 = strlen(s2); - - s = (char *)malloc(l1 + l2 + 2); - - memcpy(s, s1, l1); - if (s[l1 - 1] != '/') { - s[l1++] = '/'; - } - - memcpy(s + l1, s2, l2); - s[l1 + l2] = 0; - - return s; -} - -static char *path_append(char *s1, char *s2) -{ - return do_path_append(s1, strlen(s1), s2); -} - -static char *copy_string(char *s1) -{ - int l1; - char *s; - - if (!s1) return NULL; - - l1 = strlen(s1); - - s = (char *)malloc(l1 + 1); - - memcpy(s, s1, l1 + 1); - - return s; -} - -static int executable_exists(char *path) -{ - return (access(path, X_OK) == 0); -} - -static char *get_self_path(char *exec_file) -{ - if (exec_file[0] == '/') { - /* Absolute path */ - return exec_file; - } else if (has_slash(exec_file)) { - /* Relative path with a directory: */ - char *buf; - long buflen = 4096; - buf = (char *)malloc(buflen); - return path_append(getcwd(buf, buflen), exec_file); - } else { - /* We have to find the executable by searching PATH: */ - char *path = copy_string(getenv("PATH")), *p, *m; - int more; - - if (!path) { - path = ""; - } - - while (1) { - /* Try each element of path: */ - for (p = path; *p && (*p != ':'); p++) { } - if (*p) { - *p = 0; - more = 1; - } else - more = 0; - - if (!*path) - break; - - m = path_append(path, exec_file); - - if (executable_exists(m)) { - if (m[0] != '/') - m = path_append(getcwd(NULL, 0), m); - return m; - } - free(m); - - if (more) - path = p + 1; - else - break; - } - - return exec_file; - } -} -#endif - -#ifdef NO_GET_SEGMENT_OFFSET -static long get_segment_offset() -{ - return 0; -} #endif #ifndef WIN32 @@ -355,6 +161,7 @@ static int bytes_main(int argc, char **argv, int wm_is_gracket_or_x11_arg_count, char *gracket_guid_or_x11_args) { char *boot_exe; + self_exe_t self_exe; char *exec_file = argv[0], *run_file = NULL; char *boot1_path, *boot2_path, *boot3_path; int boot1_offset, boot2_offset, boot3_offset, boot_end_offset; @@ -374,12 +181,12 @@ static int bytes_main(int argc, char **argv, argv++; } - extract_built_in_arguments(&exec_file, &run_file, &argc, &argv); + self_exe = get_self_path(exec_file); + + extract_built_in_arguments(self_exe, &exec_file, &run_file, &argc, &argv); if (!run_file) run_file = exec_file; - segment_offset = get_segment_offset(); - memcpy(&boot1_offset, boot_file_data + boot_file_offset, sizeof(boot1_offset)); memcpy(&boot2_offset, boot_file_data + boot_file_offset + 4, sizeof(boot2_offset)); memcpy(&boot3_offset, boot_file_data + boot_file_offset + 8, sizeof(boot3_offset)); @@ -393,7 +200,7 @@ static int bytes_main(int argc, char **argv, dll = embedded_dll_open("libracketcsxxxxxxx.dll", 1); boot_rsrc_offset = in_memory_get_offset("libracketcsxxxxxxx.dll"); racket_boot_p = (racket_boot_t)scheme_dll_find_object(dll, "racket_boot"); - dll_path = get_self_executable_path(); + dll_path = self_exe; } else { HMODULE dll; dll_path = load_delayed_dll_x(NULL, "libracketcsxxxxxxx.dll", &dll); @@ -402,18 +209,19 @@ static int bytes_main(int argc, char **argv, boot_exe = string_to_utf8(dll_path); # define racket_boot racket_boot_p #else - boot_exe = get_self_path(exec_file); + boot_exe = self_exe; #endif -#ifdef ELF_FIND_BOOT_SECTION - boot_offset = find_boot_section(boot_exe); -#elif defined(OS_X) + /* segment_offset is for embedded bytecode (not boot files) */ + segment_offset = get_segment_offset(self_exe); + +#if defined(OS_X) boot_offset = find_rktboot_section(boot_exe); if (!boot_offset) boot_images_in_exe = 0; #elif WIN32 boot_offset = find_resource_offset(dll_path, 259, boot_rsrc_offset); #else - boot_offset = 0; + boot_offset = find_boot_section(boot_exe); #endif boot1_offset += boot_offset; @@ -470,6 +278,7 @@ static int bytes_main(int argc, char **argv, ba.collects_dir = extract_coldir(); ba.config_dir = extract_configdir(); ba.dll_dir = extract_dlldir(); + ba.k_file = SELF_PATH_TO_BYTES(self_exe); ba.cs_compiled_subdir = CS_COMPILED_SUBDIR; diff --git a/racket/src/cs/main.sps b/racket/src/cs/main.sps index fd5333779a..7af4adbe3b 100644 --- a/racket/src/cs/main.sps +++ b/racket/src/cs/main.sps @@ -86,13 +86,13 @@ (#%newline (#%current-error-port)) (exit 1)) - (define builtin-argc 10) + (define builtin-argc 11) (seq (unless (>= (length the-command-line-arguments) builtin-argc) (startup-error (string-append "expected `embedded-interactive-mode?`," " `exec-file`, `run-file`, `collects`, and `etc` paths" - " plus `segment-offset`, `cs-compiled-subdir?`, `is-gui?`," + " plus `k-file`, `segment-offset`, `cs-compiled-subdir?`, `is-gui?`," " `wm-is-gracket-or-x11-arg-count`, and `gracket-guid-or-x11-args`" " to start"))) (set-exec-file! (->path (list-ref the-command-line-arguments/maybe-bytes 1))) @@ -110,11 +110,14 @@ (map ->path (cdr s))))]))) (define init-config-dir (->path (or (getenv-bytes "PLTCONFIGDIR") (list-ref the-command-line-arguments/maybe-bytes 4)))) - (define segment-offset (#%string->number (list-ref the-command-line-arguments 5))) - (define cs-compiled-subdir? (string=? "true" (list-ref the-command-line-arguments 6))) - (define gracket? (string=? "true" (list-ref the-command-line-arguments 7))) - (define wm-is-gracket-or-x11-arg-count (string->number (list-ref the-command-line-arguments 8))) - (define gracket-guid-or-x11-args (list-ref the-command-line-arguments 9)) + (define k-executable-path (let ([s (list-ref the-command-line-arguments/maybe-bytes 5)]) + (and (not (or (equal? s "") (equal? s '#vu8()))) + s))) + (define segment-offset (#%string->number (list-ref the-command-line-arguments 6))) + (define cs-compiled-subdir? (string=? "true" (list-ref the-command-line-arguments 7))) + (define gracket? (string=? "true" (list-ref the-command-line-arguments 8))) + (define wm-is-gracket-or-x11-arg-count (string->number (list-ref the-command-line-arguments 9))) + (define gracket-guid-or-x11-args (list-ref the-command-line-arguments 10)) (seq (when (eq? 'windows (system-type)) @@ -415,10 +418,11 @@ (let ([n (#%string->number s)]) (unless (exact-integer? n) (startup-error "bad ~a: ~a" what s)) - (#%number->string (+ n segment-offset))))] + (#%number->string (+ n (if f 0 segment-offset)))))] [n (add-segment-offset n "starting offset")] [m (add-segment-offset m "first ending offset")] - [p (add-segment-offset p "second ending offset")]) + [p (add-segment-offset p "second ending offset")] + [f (or f k-executable-path)]) (set! loads (cons (lambda () diff --git a/racket/src/start/config.inc b/racket/src/start/config.inc index 3d10d19b76..69dcf83eeb 100644 --- a/racket/src/start/config.inc +++ b/racket/src/start/config.inc @@ -1,5 +1,36 @@ /* This code fragment embeds strings in an executable that can be - updated with various Racket exe-manipulation tools. */ + updated with various Racket exe-manipulation tools. + + Used by CS's "main.c" and BC's "cmdline.inc". + + Functions that are "exported": + + self_exe_t get_self_path(char *argv0); + void extract_built_in_arguments(const self_exe_t self_exe, + char **_prog, char **_sprog, + int *_argc, char ***_argv); + char *SELF_PATH_TO_BYTES(self_exe_t) + + char *extract_coldir(); + char *extract_configdir(); + + long get_segment_offset(self_exe_t self); // added to `-k` arguments + + Windows: + self_exe_t is wchar_t + wchar_t *extract_dlldir(); + long find_resource_offset(const wchar_t *path, int id, long delta); + char *string_to_utf8(wchar_t *p); + + Mac OS: + long find_mach_o_segment(const char *name, long *_len); + + Unix: + int find_elf_section_offset(const char *filename, + const char *name, + int *_start, int *_end); + +*/ #pragma GCC diagnostic ignored "-Wwrite-strings" @@ -99,15 +130,19 @@ static int _configdir_offset = 17; /* Skip permanent tag */ # define XFORM_OK_PLUS + #endif -#ifdef OS_X -# include -# include -# include -#endif - #ifdef DOS_FILE_SYSTEM # include +#else +# include +# include +# include +# include +# include +#endif +#include "self_exe.inc" + +#ifdef DOS_FILE_SYSTEM #ifndef DLL_RELATIVE_PATH # define DLL_RELATIVE_PATH L"lib" #endif @@ -127,40 +162,13 @@ END_XFORM_SKIP; #endif #ifdef OS_X -static long get_segment_offset() +static long get_segment_offset(const char *me) { -# if defined(__x86_64__) || defined(__arm64__) - const struct segment_command_64 *seg; -# else - const struct segment_command *seg; -#endif - seg = getsegbyname("__PLTSCHEME"); - if (seg) - return seg->fileoff; - else - return 0; + return find_mach_o_segment("__PLTSCHEME", NULL); } #endif #ifdef DOS_FILE_SYSTEM -wchar_t *get_self_executable_path() XFORM_SKIP_PROC -{ - wchar_t *path; - DWORD r, sz = 1024; - - while (1) { - path = (wchar_t *)malloc(sz * sizeof(wchar_t)); - r = GetModuleFileNameW(NULL, path, sz); - if ((r == sz) - && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { - free(path); - sz = 2 * sz; - } else - break; - } - - return path; -} static DWORD find_by_id(HANDLE fd, DWORD rsrcs, DWORD pos, int id, long delta) XFORM_SKIP_PROC { @@ -185,7 +193,7 @@ static DWORD find_by_id(HANDLE fd, DWORD rsrcs, DWORD pos, int id, long delta) X return 0; } -static long find_resource_offset(wchar_t *path, int id, long delta) XFORM_SKIP_PROC +static long find_resource_offset(const wchar_t *path, int id, long delta) XFORM_SKIP_PROC { /* Find the resource of type `id` */ HANDLE fd; @@ -258,14 +266,45 @@ static long find_resource_offset(wchar_t *path, int id, long delta) XFORM_SKIP_P } } -static long get_segment_offset() XFORM_SKIP_PROC +static long get_segment_offset(const wchar_t *me) XFORM_SKIP_PROC { - return find_resource_offset(get_self_executable_path(), 257, 0); + return find_resource_offset(me, 257, 0); +} + +static char *string_to_utf8(wchar_t *p) XFORM_SKIP_PROC +{ + char *r; + int len; + + len = WideCharToMultiByte(CP_UTF8, 0, p, -1, NULL, 0, NULL, NULL); + r = malloc(len); + len = WideCharToMultiByte(CP_UTF8, 0, p, -1, r, len, NULL, NULL); + + return r; +} + +# define SELF_PATH_TO_BYTES(s) string_to_utf8(s) + +#else + +# define SELF_PATH_TO_BYTES(s) s + +#endif + +#if !defined(OS_X) && !defined(DOS_FILE_SYSTEM) + +static long get_segment_offset(const char *me) XFORM_SKIP_PROC +{ + int start = 0, end = 0; + + (void)find_elf_section_offset(me, ".rackprog", &start, &end); + + return start; } #endif -static void extract_built_in_arguments(char **_prog, char **_sprog, int *_argc, char ***_argv) +static void extract_built_in_arguments(const self_exe_t self_exe, char **_prog, char **_sprog, int *_argc, char ***_argv) { GC_CAN_IGNORE char *prog = *_prog; GC_CAN_IGNORE char *sprog = *_sprog; @@ -321,9 +360,8 @@ static void extract_built_in_arguments(char **_prog, char **_sprog, int *_argc, the cmdline string is. It might be relative to the executable. */ HANDLE fd; - wchar_t *path; + wchar_t *path = self_exe; - path = get_self_executable_path(); fd = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, @@ -337,7 +375,7 @@ static void extract_built_in_arguments(char **_prog, char **_sprog, int *_argc, DWORD got; start = *(long *)&scheme_cmdline_exe_hack[4]; len = *(long *)&scheme_cmdline_exe_hack[8]; - start += get_segment_offset(); + start += get_segment_offset(self_exe); p = (unsigned char *)malloc(len); SetFilePointer(fd, start, 0, FILE_BEGIN); ReadFile(fd, p, len, &got, NULL); @@ -386,14 +424,12 @@ static void extract_built_in_arguments(char **_prog, char **_sprog, int *_argc, + 4); } } - free(path); } -#endif -#if defined(OS_X) +#else if (scheme_cmdline_exe_hack[0] == '?') { - long fileoff, cmdoff, cmdlen; + long fileoff, cmdoff, cmdlen, need, got; int fd; - fileoff = get_segment_offset(); + fileoff = get_segment_offset(self_exe); p = (unsigned char *)scheme_cmdline_exe_hack + 4; cmdoff = (p[0] @@ -405,14 +441,22 @@ static void extract_built_in_arguments(char **_prog, char **_sprog, int *_argc, + (((long)p[6]) << 16) + (((long)p[7]) << 24)); p = malloc(cmdlen); - - fd = open(_dyld_get_image_name(0), O_RDONLY); + + fd = open(self_exe, O_RDONLY); lseek(fd, fileoff + cmdoff, 0); - read(fd, p, cmdlen); + + for (need = cmdlen; need > 0; need -= got) { + got = read(fd, p + (cmdlen - need), need); + if (got == -1) { + got = 0; + if (errno != EINTR) + break; + } + } close(fd); } #endif - + if (!p) p = (unsigned char *)scheme_cmdline_exe_hack + 1; @@ -465,7 +509,3 @@ static char *extract_configdir() { return scheme_configdir XFORM_OK_PLUS _configdir_offset; } - -#if !defined(OS_X) && !defined(DOS_FILE_SYSTEM) -# define NO_GET_SEGMENT_OFFSET -#endif diff --git a/racket/src/start/embedded_dll.inc b/racket/src/start/embedded_dll.inc index 52ccbeed8d..b8b4d5f1cd 100644 --- a/racket/src/start/embedded_dll.inc +++ b/racket/src/start/embedded_dll.inc @@ -20,7 +20,7 @@ static HANDLE open_self() wchar_t *path; HANDLE fd; - path = get_self_executable_path(); + path = get_self_path(NULL); fd = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, @@ -38,7 +38,7 @@ static void parse_embedded_dlls() { long rsrc_pos; - rsrc_pos = find_resource_offset(get_self_executable_path(), 258, 0); + rsrc_pos = find_resource_offset(get_self_path(NULL), 258, 0); if (rsrc_pos) { HANDLE fd = open_self(); diff --git a/racket/src/start/self_exe.inc b/racket/src/start/self_exe.inc new file mode 100644 index 0000000000..6546b1f0dd --- /dev/null +++ b/racket/src/start/self_exe.inc @@ -0,0 +1,368 @@ +/* Used by "ustart.c" and "config.inc". + + Defines self_exe_t get_self_path(char *exec_file), + which takes argv[0] and returns an improved representation of + the containing executable. At worst, on Unix, uses `PATH` to + convert `exec_file` into a path. + + On Mac (even XonX), `find_mach_o_segment` is also defined. + + On Unix (not Mac OS, not even XonX), `find_elf_section` + is also defined. + + If USE_EXE_LOOKUP_VIA_PATH, also: `lookup_exe_via_path`, + `path_append`, and `do_path_append`. +*/ + +#define USE_GENERIC_GET_SELF_PATH + +#ifdef DOS_FILE_SYSTEM +typedef wchar_t *self_exe_t; +#else +typedef char *self_exe_t; +#endif + +#if defined(__linux__) +# include +# include +static char *get_self_path(char *exec_file) +{ + char buf[256], *s = buf; + ssize_t len, blen = sizeof(buf); + + while (1) { + len = readlink("/proc/self/exe", s, blen-1); + if (len == (blen-1)) { + if (s != buf) free(s); + blen *= 2; + s = malloc(blen); + } else if (len < 0) { + fprintf(stderr, "failed to get self (%d)\n", errno); + exit(1); + } else + break; + } + buf[len] = 0; + return strdup(buf); +} +# undef USE_GENERIC_GET_SELF_PATH +#endif + +#if defined(__FreeBSD__) || defined(__NetBSD__) +# include +# include +static char *get_self_path(char *exec_file) +{ + int mib[4]; + char *s; + size_t len; + int r; + + mib[0] = CTL_KERN; +#if defined(__NetBSD__) + mib[1] = KERN_PROC_ARGS; + mib[2] = getpid(); + mib[3] = KERN_PROC_PATHNAME; +#else + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; +#endif + + r = sysctl(mib, 4, NULL, &len, NULL, 0); + if (r < 0) { + fprintf(stderr, "failed to get self (%d)\n", errno); + exit(1); + } + s = malloc(len); + r = sysctl(mib, 4, s, &len, NULL, 0); + if (r < 0) { + fprintf(stderr, "failed to get self (%d)\n", errno); + exit(1); + } + return s; +} +# undef USE_GENERIC_GET_SELF_PATH +#endif + +#if defined(__APPLE__) && defined(__MACH__) +# include +# include +static char *get_self_path(char *exec_file) +{ + char buf[1024], *s; + uint32_t size = sizeof(buf); + int r; + + r = _NSGetExecutablePath(buf, &size); + if (!r) + return strdup(buf); + else { + s = malloc(size); + r = _NSGetExecutablePath(s, &size); + if (!r) + return s; + fprintf(stderr, "failed to get self\n"); + exit(1); + } +} +# undef USE_GENERIC_GET_SELF_PATH + +static long find_mach_o_segment(const char *name, long *_len) +{ +# if defined(__x86_64__) || defined(__arm64__) + const struct segment_command_64 *seg; +# else + const struct segment_command *seg; +#endif + seg = getsegbyname(name); + if (seg) { + if (_len) + *_len = seg->filesize; + return seg->fileoff; + } else + return 0; +} +#endif + +#ifdef DOS_FILE_SYSTEM +/* used outside this file: */ +wchar_t *get_self_path(char *exec_file) XFORM_SKIP_PROC +{ + wchar_t *path; + DWORD r, sz = 1024; + + while (1) { + path = (wchar_t *)malloc(sz * sizeof(wchar_t)); + r = GetModuleFileNameW(NULL, path, sz); + if ((r == sz) + && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { + free(path); + sz = 2 * sz; + } else + break; + } + + return path; +} +# undef USE_GENERIC_GET_SELF_PATH +#endif + +#if defined(USE_GENERIC_GET_SELF_PATH) || defined(USE_EXE_LOOKUP_VIA_PATH) + +/* Get executable path via argv[0] and the `PATH` environment variable */ + +static int has_slash(char *s) XFORM_SKIP_PROC +{ + while (*s) { + if (s[0] == '/') + return 1; + s++; + } + return 0; +} + +static char *do_path_append(char *s1, int l1, char *s2) XFORM_SKIP_PROC +{ + int l2; + char *s; + + l2 = strlen(s2); + + s = (char *)malloc(l1 + l2 + 2); + + memcpy(s, s1, l1); + if (s[l1 - 1] != '/') { + s[l1++] = '/'; + } + + memcpy(s + l1, s2, l2); + s[l1 + l2] = 0; + + return s; +} + +static char *path_append(char *s1, char *s2) XFORM_SKIP_PROC +{ + return do_path_append(s1, strlen(s1), s2); +} + +static char *copy_string(char *s1) XFORM_SKIP_PROC +{ + int l1; + char *s; + + if (!s1) return NULL; + + l1 = strlen(s1); + + s = (char *)malloc(l1 + 1); + + memcpy(s, s1, l1 + 1); + + return s; +} + +static int executable_exists(char *path) XFORM_SKIP_PROC +{ + return (access(path, X_OK) == 0); +} + +static char *lookup_exe_via_path(char *exec_file) XFORM_SKIP_PROC +{ + if (exec_file[0] == '/') { + /* Absolute path */ + return exec_file; + } else if (has_slash(exec_file)) { + /* Relative path with a directory: */ + char *buf; + long buflen = 4096; + buf = (char *)malloc(buflen); + return path_append(getcwd(buf, buflen), exec_file); + } else { + /* We have to find the executable by searching PATH: */ + char *path = copy_string(getenv("PATH")), *p, *m; + int more; + + if (!path) { + path = ""; + } + + while (1) { + /* Try each element of path: */ + for (p = path; *p && (*p != ':'); p++) { } + if (*p) { + *p = 0; + more = 1; + } else + more = 0; + + if (!*path) + break; + + m = path_append(path, exec_file); + + if (executable_exists(m)) { + if (m[0] != '/') + m = path_append(getcwd(NULL, 0), m); + return m; + } + free(m); + + if (more) + path = p + 1; + else + break; + } + + return exec_file; + } +} +#endif + +#ifdef USE_GENERIC_GET_SELF_PATH +static char *get_self_path(char *exec_file) +{ + return lookup_exe_via_path(exec_file); +} +#endif + +#if !defined(OS_X) && !defined(DOS_FILE_SYSTEM) + +#include +#include +#include + +typedef unsigned short ELF__Half; +typedef unsigned int ELF__Word; +typedef unsigned long ELF__Xword; +typedef unsigned long ELF__Addr; +typedef unsigned long ELF__Off; + +typedef struct { + unsigned char e_ident[16]; + ELF__Half e_type; + ELF__Half e_machine; + ELF__Word e_version; + ELF__Addr e_entry; + ELF__Off e_phoff; + ELF__Off e_shoff; + ELF__Word e_flags; + ELF__Half e_ehsize; + ELF__Half e_phentsize; + ELF__Half e_phnum; + ELF__Half e_shentsize; + ELF__Half e_shnum; + ELF__Half e_shstrndx; +} ELF__Header; + +typedef struct +{ + ELF__Word sh_name; + ELF__Word sh_type; + ELF__Xword sh_flags; + ELF__Addr sh_addr; + ELF__Off sh_offset; + ELF__Xword sh_size; + ELF__Word sh_link; + ELF__Word sh_info; + ELF__Xword sh_addralign; + ELF__Xword sh_entsize; +} Elf__Shdr; + +static int find_elf_section_offset(const char *filename, + const char *name, + int *_start, int *_end) XFORM_SKIP_PROC +{ + int fd, i; + ELF__Header e; + Elf__Shdr s; + char *strs; + + fd = open(filename, O_RDONLY, 0); + if (fd == -1) return 0; + + if (read(fd, &e, sizeof(e)) == sizeof(e)) { + if ((e.e_ident[0] == 0x7F) + && (e.e_ident[1] == 'E') + && (e.e_ident[2] == 'L') + && (e.e_ident[3] == 'F')) { + + lseek(fd, e.e_shoff + (e.e_shstrndx * e.e_shentsize), SEEK_SET); + if (read(fd, &s, sizeof(s)) != sizeof(s)) { + close(fd); + return 0; + } + + strs = (char *)malloc(s.sh_size); + lseek(fd, s.sh_offset, SEEK_SET); + if (read(fd, strs, s.sh_size) != s.sh_size) { + close(fd); + free(strs); + return 0; + } + + for (i = 0; i < e.e_shnum; i++) { + lseek(fd, e.e_shoff + (i * e.e_shentsize), SEEK_SET); + if (read(fd, &s, sizeof(s)) != sizeof(s)) { + close(fd); + return 0; + } + if (!strcmp(strs + s.sh_name, name)) { + *_start = s.sh_offset; + *_end = s.sh_offset + s.sh_size; + close(fd); + free(strs); + return 1; + } + } + + free(strs); + } + } + + close(fd); + return 0; +} + +#endif diff --git a/racket/src/start/unix_self.inc b/racket/src/start/unix_self.inc deleted file mode 100644 index b2ee738eba..0000000000 --- a/racket/src/start/unix_self.inc +++ /dev/null @@ -1,86 +0,0 @@ -#define USE_GENERIC_GET_SELF_PATH - -#if defined(__linux__) -# include -static char *get_self_path(char *exec_file) -{ - char buf[256], *s = buf; - ssize_t len, blen = sizeof(buf); - - while (1) { - len = readlink("/proc/self/exe", s, blen-1); - if (len == (blen-1)) { - if (s != buf) free(s); - blen *= 2; - s = malloc(blen); - } else if (len < 0) { - fprintf(stderr, "failed to get self (%d)\n", errno); - exit(1); - } else - break; - } - buf[len] = 0; - return strdup(buf); -} -# undef USE_GENERIC_GET_SELF_PATH -#endif - -#if defined(__FreeBSD__) || defined(__NetBSD__) -# include -# include -static char *get_self_path(char *exec_file) -{ - int mib[4]; - char *s; - size_t len; - int r; - - mib[0] = CTL_KERN; -#if defined(__NetBSD__) - mib[1] = KERN_PROC_ARGS; - mib[2] = getpid(); - mib[3] = KERN_PROC_PATHNAME; -#else - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PATHNAME; - mib[3] = -1; -#endif - - r = sysctl(mib, 4, NULL, &len, NULL, 0); - if (r < 0) { - fprintf(stderr, "failed to get self (%d)\n", errno); - exit(1); - } - s = malloc(len); - r = sysctl(mib, 4, s, &len, NULL, 0); - if (r < 0) { - fprintf(stderr, "failed to get self (%d)\n", errno); - exit(1); - } - return s; -} -# undef USE_GENERIC_GET_SELF_PATH -#endif - -#if defined(__APPLE__) && defined(__MACH__) -# include -static char *get_self_path(char *exec_file) -{ - char buf[1024], *s; - uint32_t size = sizeof(buf); - int r; - - r = _NSGetExecutablePath(buf, &size); - if (!r) - return strdup(buf); - else { - s = malloc(size); - r = _NSGetExecutablePath(s, &size); - if (!r) - return s; - fprintf(stderr, "failed to get self\n"); - exit(1); - } -} -# undef USE_GENERIC_GET_SELF_PATH -#endif diff --git a/racket/src/start/ustart.c b/racket/src/start/ustart.c index 1dc24888c6..403850bc1e 100644 --- a/racket/src/start/ustart.c +++ b/racket/src/start/ustart.c @@ -95,6 +95,10 @@ char * volatile _configdir = "coNFIg dIRECTORy:" /* <- this tag stays, so we can "****************************************************************"; static int _configdir_offset = 17; /* Skip permanent tag */ +#define XFORM_SKIP_PROC /* empty */ +#define USE_EXE_LOOKUP_VIA_PATH +#include "self_exe.inc" + typedef struct { char *flag; int arg_count; @@ -174,68 +178,12 @@ static char *string_append(char *s1, char *s2) return s; } -static char *copy_string(char *s1) -{ - int l1; - char *s; - - if (!s1) return NULL; - - l1 = strlen(s1); - - s = (char *)malloc(l1 + 1); - - memcpy(s, s1, l1 + 1); - - return s; -} - -static char *do_path_append(char *s1, int l1, char *s2) -{ - int l2; - char *s; - - l2 = strlen(s2); - - s = (char *)malloc(l1 + l2 + 2); - - memcpy(s, s1, l1); - if (s[l1 - 1] != '/') { - s[l1++] = '/'; - } - - memcpy(s + l1, s2, l2); - s[l1 + l2] = 0; - - return s; -} - -static char *path_append(char *s1, char *s2) -{ - return do_path_append(s1, strlen(s1), s2); -} - -static int executable_exists(char *path) -{ - return (access(path, X_OK) == 0); -} - static int as_int(char *_c) { unsigned char *c = (unsigned char *)_c; return c[0] | ((int)c[1] << 8) | ((int)c[2] << 16) | ((int)c[3] << 24); } -static int has_slash(char *s) -{ - while (*s) { - if (s[0] == '/') - return 1; - s++; - } - return 0; -} - char *absolutize(char *p, char *d) { int l1; @@ -262,107 +210,30 @@ static char *next_string(char *s) return s + strlen(s) + 1; } -#include "unix_self.inc" - -#ifdef USE_GENERIC_GET_SELF_PATH -static char *adjust_self_reference(char *me) +static int try_section_shift(const char *me, int *_start, int *_decl_end, int *_prog_end, int *_end) { - return me; -} + int start = 0, end = 0; + int is_prog; + +#ifdef OS_X + { + long len = 0; + start = find_mach_o_segment("__PLTSCHEME", &len); + end = start + len; + is_prog = 1; + } #else -static char *adjust_self_reference(char *me) -{ - return get_self_path(me); -} + is_prog = find_elf_section_offset(me, ".rackprog", &start, &end); #endif -typedef unsigned short ELF__Half; -typedef unsigned int ELF__Word; -typedef unsigned long ELF__Xword; -typedef unsigned long ELF__Addr; -typedef unsigned long ELF__Off; - -typedef struct { - unsigned char e_ident[16]; - ELF__Half e_type; - ELF__Half e_machine; - ELF__Word e_version; - ELF__Addr e_entry; - ELF__Off e_phoff; - ELF__Off e_shoff; - ELF__Word e_flags; - ELF__Half e_ehsize; - ELF__Half e_phentsize; - ELF__Half e_phnum; - ELF__Half e_shentsize; - ELF__Half e_shnum; - ELF__Half e_shstrndx; -} ELF__Header; - -typedef struct -{ - ELF__Word sh_name; - ELF__Word sh_type; - ELF__Xword sh_flags; - ELF__Addr sh_addr; - ELF__Off sh_offset; - ELF__Xword sh_size; - ELF__Word sh_link; - ELF__Word sh_info; - ELF__Xword sh_addralign; - ELF__Xword sh_entsize; -} Elf__Shdr; - -static int try_elf_section(const char *me, int *_start, int *_decl_end, int *_prog_end, int *_end) -{ - int fd, i; - ELF__Header e; - Elf__Shdr s; - char *strs; - - fd = open(me, O_RDONLY, 0); - if (fd == -1) return 0; - - if (read(fd, &e, sizeof(e)) == sizeof(e)) { - if ((e.e_ident[0] == 0x7F) - && (e.e_ident[1] == 'E') - && (e.e_ident[2] == 'L') - && (e.e_ident[3] == 'F')) { - - lseek(fd, e.e_shoff + (e.e_shstrndx * e.e_shentsize), SEEK_SET); - if (read(fd, &s, sizeof(s)) != sizeof(s)) { - close(fd); - return 0; - } - - strs = (char *)malloc(s.sh_size); - lseek(fd, s.sh_offset, SEEK_SET); - if (read(fd, strs, s.sh_size) != s.sh_size) { - close(fd); - return 0; - } - - for (i = 0; i < e.e_shnum; i++) { - lseek(fd, e.e_shoff + (i * e.e_shentsize), SEEK_SET); - if (read(fd, &s, sizeof(s)) != sizeof(s)) { - close(fd); - return 0; - } - if (!strcmp(strs + s.sh_name, ".rackcmdl") - || !strcmp(strs + s.sh_name, ".rackprog")) { - *_decl_end = (*_decl_end - *_start) + s.sh_offset; - *_prog_end = (*_prog_end - *_start) + s.sh_offset; - *_start = s.sh_offset; - *_end = s.sh_offset + s.sh_size; - close(fd); - return !strcmp(strs + s.sh_name, ".rackprog"); - } - } - } + if (start != 0) { + *_decl_end = (*_decl_end - *_start) + start; + *_prog_end = (*_prog_end - *_start) + start; + *_start = start; + *_end = end; } - close(fd); - return 0; + return is_prog; } int main(int argc, char **argv) @@ -379,52 +250,7 @@ int main(int argc, char **argv) return 1; } - if (me[0] == '/') { - /* Absolute path */ - } else if (has_slash(me)) { - /* Relative path with a directory: */ - char *buf; - long buflen = 4096; - buf = (char *)malloc(buflen); - me = path_append(getcwd(buf, buflen), me); - free(buf); - } else { - /* We have to find the executable by searching PATH: */ - char *path = copy_string(getenv("PATH")), *p, *m; - int more; - - if (!path) { - path = ""; - } - - while (1) { - /* Try each element of path: */ - for (p = path; *p && (*p != ':'); p++) { } - if (*p) { - *p = 0; - more = 1; - } else - more = 0; - - if (!*path) - break; - - m = path_append(path, me); - - if (executable_exists(m)) { - if (m[0] != '/') - m = path_append(getcwd(NULL, 0), m); - me = m; - break; - } - free(m); - - if (more) - path = p + 1; - else - break; - } - } + me = lookup_exe_via_path(me); /* me is now an absolute path to the binary */ @@ -451,7 +277,7 @@ int main(int argc, char **argv) /* use `me` for `-k`, unless we have a way to more directly get the executable file that contains embedded code; if we do, then argv[0] doesn't have to match the executable */ - embedding_me = adjust_self_reference(me); + embedding_me = get_self_path(me); start = as_int(config + 8); decl_end = as_int(config + 12); @@ -460,7 +286,7 @@ int main(int argc, char **argv) count = as_int(config + 24); x11 = as_int(config + 28); - fix_argv = try_elf_section(embedding_me, &start, &decl_end, &prog_end, &end); + try_section_shift(embedding_me, &start, &decl_end, &prog_end, &end); { int offset, len; @@ -566,13 +392,11 @@ int main(int argc, char **argv) new_argv[argpos++] = "-G"; new_argv[argpos++] = absolutize(_configdir + _configdir_offset, me); - if (fix_argv) { - /* next four args are "-k" and numbers; leave room to insert the - filename in place of "-k", and fix the numbers to match start, - decl_end, and prog_end */ - new_argv[argpos++] = "-Y"; - fix_argv = argpos; - } + /* next four args are "-k" and numbers; leave room to insert the + filename in place of "-k", and fix the numbers to match start, + decl_end, and prog_end */ + new_argv[argpos++] = "-Y"; + fix_argv = argpos; /* Add built-in flags: */ while (count--) { diff --git a/racket/src/worksp/.gitignore b/racket/src/worksp/.gitignore index bedb80ed2a..47ee5b5912 100644 --- a/racket/src/worksp/.gitignore +++ b/racket/src/worksp/.gitignore @@ -42,3 +42,6 @@ cstartup.exe /liblz4.dll /liblz4.lib /liblz4.exp +/liblz4mt.dll +/liblz4mt.lib +/liblz4mt.exp