diff --git a/ape/ape.S b/ape/ape.S index 42a088287..c22c0fcd9 100644 --- a/ape/ape.S +++ b/ape/ape.S @@ -540,11 +540,32 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang // modify the binary to follow the local system's convention. // There isn't a one-size-fits-all approach for this, thus we // present two choices. + .ascii "o=\"$(command -v \"$0\")\"\n" +// Try to use a system-wide APE loader. + .ascii "type ape-loader >/dev/null 2>&1 && " + .ascii "exec ape-loader \"$0\" \"$@\"\n" +#ifdef APE_LOADER +// There is no system-wide APE loader, but there is one +// embedded inside the APE. So if the system is not MacOs, +// extract the loader into a temp folder, and use it to +// load the APE without modifying it. + .ascii "if [ ! -d /Applications ]; then\n" + .ascii "t=\"${TMPDIR:-/tmp}/ape-loader.$$\"\n" + .ascii "dd if=\"$o\" of=\"$t\" skip=\"" + .shstub ape_loader_dd_skip,2 + .ascii "\" count=\"" + .shstub ape_loader_dd_count,2 + .ascii "\" bs=\"" + .shstub ape_loader_dd_bs,2 + .ascii "\" 2>/dev/null\n" + .ascii "chmod 700 \"$t\"\n" + .ascii "exec \"$t\" \"$0\" \"$@\"\n" + .ascii "fi\n" +#endif #ifndef APE_NO_MODIFY_SELF // The default behavior is: to overwrite the header in place. // We prefer this because it's a tiny constant one time cost. // We simply printf a 64-byte header and call execve() again. - .ascii "o=\"$(command -v \"$0\")\"\n" #ifdef APE_BUILDSAFE // This code is intended for binaries in build/bootstrap/. It // causes them to not self-modify since they're checked-in to @@ -645,6 +666,11 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang .ascii "fi\n" .ascii "exit $R\n" .endobj apesh +#ifdef APE_LOADER + .section .ape.loader,"a",@progbits + .incbin APE_LOADER + .previous +#endif /* APE_LOADER */ #endif /* SupportsWindows() || SupportsMetal() || SupportsXnu() */ #if SupportsSystemv() || SupportsMetal() diff --git a/ape/ape.lds b/ape/ape.lds index 794109bf4..06ef7bad3 100644 --- a/ape/ape.lds +++ b/ape/ape.lds @@ -204,6 +204,13 @@ SECTIONS { KEEP(*(.apesh)) KEEP(*(.head2)) KEEP(*(.text.head)) + + /* Loader */ + . = ALIGN(64); + HIDDEN(ape_loader = .); + KEEP(*(.ape.loader)) + . = ALIGN(64); + HIDDEN(ape_loader_end = .); /* Executable & Linkable Format */ . = ALIGN(__SIZEOF_POINTER__); @@ -478,6 +485,17 @@ HIDDEN(ape_stack_filesz = 0); HIDDEN(ape_stack_memsz = STACKSIZE); HIDDEN(ape_stack_align = 16); +HIDDEN(ape_loader_offset = ape_rom_offset + ape_loader - ape_rom_vaddr); +HIDDEN(ape_loader_vaddr = ape_loader); +HIDDEN(ape_loader_paddr = ape_rom_paddr + ape_loader_offset); +HIDDEN(ape_loader_filesz = ape_loader_end - ape_loader); +HIDDEN(ape_loader_memsz = ape_loader_filesz); +HIDDEN(ape_loader_align = 64); +HIDDEN(ape_loader_rva = RVA(ape_loader_vaddr)); +SHSTUB2(ape_loader_dd_bs, ape_loader_align); +SHSTUB2(ape_loader_dd_skip, ape_loader_rva / ape_loader_align); +SHSTUB2(ape_loader_dd_count, ape_loader_filesz / ape_loader_align); + HIDDEN(ape_note_offset = ape_rom_offset + (ape_note - ape_rom_vaddr)); HIDDEN(ape_note_vaddr = ape_note); HIDDEN(ape_note_paddr = ape_rom_paddr + ape_note_offset); @@ -589,6 +607,13 @@ CHURN(ape_elf_shnum); CHURN(ape_elf_shoff); CHURN(ape_elf_shstrndx); CHURN(ape_macho_end); +CHURN(ape_loader_offset); +CHURN(ape_loader_vaddr); +CHURN(ape_loader_paddr); +CHURN(ape_loader_filesz); +CHURN(ape_loader_memsz); +CHURN(ape_loader_align); +CHURN(ape_loader_rva); CHURN(ape_note); CHURN(ape_note_align); CHURN(ape_note_end); diff --git a/ape/ape.mk b/ape/ape.mk index 0a75630b0..af3e277f4 100644 --- a/ape/ape.mk +++ b/ape/ape.mk @@ -51,8 +51,8 @@ o/ape/idata.inc: \ $(APE_OBJS): $(BUILD_FILES) \ ape/ape.mk -o/$(MODE)/ape/ape-no-modify-self.o: ape/ape.S - @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -DAPE_NO_MODIFY_SELF $< +o/$(MODE)/ape/ape-no-modify-self.o: ape/ape.S o/$(MODE)/examples/loader.elf + @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -DAPE_LOADER="\"o/$(MODE)/examples/loader.elf\"" -DAPE_NO_MODIFY_SELF $< o/$(MODE)/ape/ape-buildsafe.o: ape/ape.S @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -DAPE_BUILDSAFE $<