mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-13 12:26:30 +00:00
Add -k OSNAME flag to apelink (#1383)
Let's say you pass the `-M blink-mips.elf` flag to apelink, so that your ape binary will bundle a compressed build of blink, and the shell script will extract that binary and launch your program under it, if running on a MIPS system. However, for any given microprocessor architecture, we'll need a separate loader for each operating system. The issue is ELF OSABI isn't very useful. As an example, SerenityOS and Linux both have SYSV in the OSABI field. So to tell their binaries apart we'd have to delve into various other conventions, like special sections and PT_NOTE structures. To make things simple this change introduces the `-k OS` flag to apelink which generate shell script content that ensures `OS` matches `uname -s` before attempting to execute a loader. For example, you could say: apelink -k Linux -M blink-linux-arm.elf -M blink-linux-mips.elf \ -k Darwin -M blink-darwin-ppc.elf \ ... To introduce support for old 32-bit architectures on multiple OSes, when building your cosmo binary.
This commit is contained in:
parent
b235492e71
commit
7b69652854
1 changed files with 39 additions and 7 deletions
|
@ -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;
|
||||
const char *kernel;
|
||||
};
|
||||
|
||||
struct Loaders {
|
||||
|
@ -244,6 +252,7 @@ static struct Inputs inputs;
|
|||
static char ape_heredoc[15];
|
||||
static enum Strategy strategy;
|
||||
static struct Loaders loaders;
|
||||
static const char *loader_kernel;
|
||||
static const char *custom_sh_code;
|
||||
static bool force_bypass_binfmt_misc;
|
||||
static bool generate_debuggable_binary;
|
||||
|
@ -979,13 +988,19 @@ 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;
|
||||
loader->kernel = loader_kernel;
|
||||
}
|
||||
|
||||
static void SetLoaderKernel(const char *kernel) {
|
||||
loader_kernel = kernel;
|
||||
}
|
||||
|
||||
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 +1024,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 +1651,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) {
|
||||
p = stpcpy(p, " && [ \"$k\" = ");
|
||||
p = stpcpy(p, loader->kernel);
|
||||
p = stpcpy(p, " ]");
|
||||
}
|
||||
|
||||
return stpcpy(p, "; then\n");
|
||||
}
|
||||
|
||||
static char *FinishGeneratingDosHeader(char *p) {
|
||||
|
@ -1892,7 +1919,8 @@ 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 &&
|
||||
strcmp(loaders.p[i].kernel, loaders.p[j].kernel) == 0) {
|
||||
Die(prog, "multiple ape loaders specified for the same platform");
|
||||
}
|
||||
}
|
||||
|
@ -2206,6 +2234,10 @@ 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) {
|
||||
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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue