mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-06 03:08:31 +00:00
Add APE interpreter example (#263)
This commit is contained in:
parent
5b60e5a37d
commit
969174e155
7 changed files with 210 additions and 14 deletions
|
@ -30,7 +30,8 @@ EXAMPLES_COMS = \
|
|||
|
||||
EXAMPLES_BINS = \
|
||||
$(EXAMPLES_COMS) \
|
||||
$(EXAMPLES_COMS:%=%.dbg)
|
||||
$(EXAMPLES_COMS:%=%.dbg) \
|
||||
o/$(MODE)/examples/loader.elf
|
||||
|
||||
EXAMPLES_DIRECTDEPS = \
|
||||
DSP_CORE \
|
||||
|
@ -130,6 +131,15 @@ o/$(MODE)/examples/nesemu1.com.dbg: \
|
|||
$(APE)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/examples/loader.o: \
|
||||
OVERRIDE_CCFLAGS += \
|
||||
-fno-record-gcc-switches
|
||||
|
||||
o/$(MODE)/examples/loader.elf: \
|
||||
o/$(MODE)/examples/loader.o \
|
||||
examples/loader.lds
|
||||
@$(ELFLINK) -s -z max-page-size=0x10
|
||||
|
||||
$(EXAMPLES_OBJS): examples/examples.mk
|
||||
|
||||
usr/share/dict/words: usr/share/dict/words.gz
|
||||
|
|
98
examples/loader.c
Normal file
98
examples/loader.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/elf/struct/ehdr.h"
|
||||
#include "libc/elf/struct/phdr.h"
|
||||
#include "libc/linux/close.h"
|
||||
#include "libc/linux/exit.h"
|
||||
#include "libc/linux/fstat.h"
|
||||
#include "libc/linux/mmap.h"
|
||||
#include "libc/linux/open.h"
|
||||
|
||||
/**
|
||||
* @fileoverview 704-byte APE executing payload for Linux, e.g.
|
||||
*
|
||||
* m=tiny
|
||||
* make -j8 MODE=$m o/$m/examples
|
||||
* o/$m/examples/loader.elf o/$m/examples/printargs.com
|
||||
*
|
||||
* @note this can probably be used as a binfmt_misc interpreter
|
||||
*/
|
||||
|
||||
#define O_RDONLY 0
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
#define PROT_EXEC 4
|
||||
#define MAP_SHARED 1
|
||||
#define MAP_PRIVATE 2
|
||||
#define MAP_FIXED 16
|
||||
#define MAP_ANONYMOUS 32
|
||||
|
||||
asm(".globl\t_start\n\t"
|
||||
"_start:\n\t"
|
||||
"mov\t%rsp,%rdi\n\t"
|
||||
"jmp\tloader");
|
||||
|
||||
static noasan noubsan void spawn(long *sp, char *b) {
|
||||
struct Elf64_Ehdr *e;
|
||||
struct Elf64_Phdr *h;
|
||||
e = (void *)b;
|
||||
h = (void *)(b + e->e_phoff);
|
||||
if (LinuxMmap((void *)(h[1].p_vaddr + h[1].p_filesz),
|
||||
h[1].p_memsz - h[1].p_filesz, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0) > 0) {
|
||||
sp[1] = sp[0] - 1;
|
||||
asm volatile("mov\t%2,%%rsp\n\t"
|
||||
"jmpq\t*%1"
|
||||
: /* no outputs */
|
||||
: "D"(0), "S"((void *)e->e_entry), "d"(sp + 1)
|
||||
: "memory");
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
noasan noubsan void loader(long *sp) {
|
||||
struct stat st;
|
||||
int c, i, fd, argc;
|
||||
char *b, *p, *q, **argv;
|
||||
argc = *sp;
|
||||
argv = (char **)(sp + 1);
|
||||
if (argc > 1 && (fd = LinuxOpen(argv[1], O_RDONLY, 0)) >= 0 &&
|
||||
!LinuxFstat(fd, &st) &&
|
||||
(b = (char *)LinuxMmap((void *)0x400000, st.st_size,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_FIXED, fd, 0)) > 0) {
|
||||
LinuxClose(fd);
|
||||
if (READ32LE(b) == READ32LE("\177ELF")) {
|
||||
spawn(sp, b);
|
||||
} else {
|
||||
for (p = b; p < b + st.st_size; ++p) {
|
||||
if (READ64LE(p) == READ64LE("printf '")) {
|
||||
for (q = b, p += 8; (c = *p++) != '\'';) {
|
||||
if (c == '\\') {
|
||||
c = *p++ - '0';
|
||||
if ('0' <= *p && *p <= '7') c *= 8, c += *p++ - '0';
|
||||
if ('0' <= *p && *p <= '7') c *= 8, c += *p++ - '0';
|
||||
}
|
||||
*q++ = c;
|
||||
}
|
||||
if (READ32LE(b) == READ32LE("\177ELF")) {
|
||||
spawn(sp, b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LinuxExit(127);
|
||||
}
|
66
examples/loader.lds
Normal file
66
examples/loader.lds
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
|
||||
. = 0x200000 + SIZEOF_HEADERS;
|
||||
|
||||
.text : {
|
||||
*(.text .text.*)
|
||||
*(.rodata .rodata.*)
|
||||
*(.data .data.*)
|
||||
*(.bss .bss.*)
|
||||
}
|
||||
|
||||
.gnu_debuglink 0 : { *(.gnu_debuglink) }
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.*)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue