diff --git a/tool/build/apelink.c b/tool/build/apelink.c index e7d2debc8..f2cd26bcb 100644 --- a/tool/build/apelink.c +++ b/tool/build/apelink.c @@ -85,6 +85,13 @@ " executable will self-modify its header on\n" \ " the first run, to use the platform format\n" \ "\n" \ + " -k KERNEL test for maching kernel name [repeatable]\n" \ + " when set, the shell script for subsequent\n" \ + " loader executables will check if uname -s\n" \ + " output matches the kernel string, only if\n" \ + " the loader executable architecture is not\n" \ + " an architecture in the input binary list\n" \ + "\n" \ " -M PATH bundle ape loader source code file for m1\n" \ " processors running the xnu kernel so that\n" \ " it can be compiled on the fly by xcode\n" \ @@ -213,6 +220,7 @@ struct Loader { char *ddarg_size1; char *ddarg_skip2; char *ddarg_size2; + char kernel[64]; }; struct Loaders { @@ -244,6 +252,7 @@ static struct Inputs inputs; static char ape_heredoc[15]; static enum Strategy strategy; static struct Loaders loaders; +static char loader_kernel[64] = {'\0'}; static const char *custom_sh_code; static bool force_bypass_binfmt_misc; static bool generate_debuggable_binary; @@ -979,13 +988,24 @@ static void AddLoader(const char *path) { if (loaders.n == ARRAYLEN(loaders.p)) { Die(prog, "too many loaders"); } - loaders.p[loaders.n++].path = path; + struct Loader *loader = &loaders.p[loaders.n++]; + loader->path = path; + if (loader_kernel[0] != '\0') { + strncpy(loader->kernel, loader_kernel, sizeof(loader->kernel)); + } else { + loader->kernel[0] = '\0'; + } +} + +static void SetLoaderKernel(const char *kernel) { + strncpy(loader_kernel, kernel, sizeof(loader_kernel)); + loader_kernel[sizeof(loader_kernel) - 1] = 0; } static void GetOpts(int argc, char *argv[]) { int opt, bits; bool got_support_vector = false; - while ((opt = getopt(argc, argv, "hvgsGBo:l:S:M:V:")) != -1) { + while ((opt = getopt(argc, argv, "hvgsGBo:l:k:S:M:V:")) != -1) { switch (opt) { case 'o': outpath = optarg; @@ -1009,6 +1029,10 @@ static void GetOpts(int argc, char *argv[]) { HashInputString("-l"); AddLoader(optarg); break; + case 'k': + HashInputString("-k"); + SetLoaderKernel(optarg); + break; case 'S': HashInputString("-S"); HashInputString(optarg); @@ -1632,16 +1656,24 @@ static char *GenerateScriptIfMachine(char *p, struct Input *in) { static char *GenerateScriptIfLoaderMachine(char *p, struct Loader *loader) { if (loader->machine == EM_NEXGEN32E) { - return stpcpy(p, "if [ \"$m\" = x86_64 ] || [ \"$m\" = amd64 ]; then\n"); + p = stpcpy(p, "if [ \"$m\" = x86_64 ] || [ \"$m\" = amd64 ]"); } else if (loader->machine == EM_AARCH64) { - return stpcpy(p, "if [ \"$m\" = aarch64 ] || [ \"$m\" = arm64 ]; then\n"); + p = stpcpy(p, "if [ \"$m\" = aarch64 ] || [ \"$m\" = arm64 ]"); } else if (loader->machine == EM_PPC64) { - return stpcpy(p, "if [ \"$m\" = ppc64le ]; then\n"); + p = stpcpy(p, "if [ \"$m\" = ppc64le ]"); } else if (loader->machine == EM_MIPS) { - return stpcpy(p, "if [ \"$m\" = mips64 ]; then\n"); + p = stpcpy(p, "if [ \"$m\" = mips64 ]"); } else { Die(loader->path, "unsupported cpu architecture"); } + + if (loader->kernel[0] != '\0') { + p = stpcpy(p, " && [ \"$k\" = "); + p = stpcpy(p, loader->kernel); + p = stpcpy(p, " ]"); + } + + return stpcpy(p, "; then\n"); } static char *FinishGeneratingDosHeader(char *p) { @@ -1892,7 +1924,9 @@ int main(int argc, char *argv[]) { for (i = 0; i < loaders.n; ++i) { for (j = i + 1; j < loaders.n; ++j) { if (loaders.p[i].os == loaders.p[j].os && - loaders.p[i].machine == loaders.p[j].machine) { + loaders.p[i].machine == loaders.p[j].machine && + strncmp(loaders.p[i].kernel, loaders.p[j].kernel, + sizeof(loaders.p[i].kernel)) == 0) { Die(prog, "multiple ape loaders specified for the same platform"); } } @@ -2206,6 +2240,20 @@ int main(int argc, char *argv[]) { } // extract the ape loader for non-input architectures + // if the user requested a host kernel check, get the host kernel + if (loader_kernel[0] != '\0') { + bool hasunused = false; + for (i = 0; i < loaders.n; ++i) { + struct Loader *loader = loaders.p + i; + if (!loader->used) { + hasunused = true; + break; + } + } + if (hasunused) { + p = stpcpy(p, "k=$(uname -s 2>/dev/null) || k=unknown\n"); + } + } for (i = 0; i < loaders.n; ++i) { struct Loader *loader = loaders.p + i; if (loader->used) {