mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Bump support up to FreeBSD 13 and NetBSD 9.2
These releases are really exciting since they contained the patches we worked to get upstreamed. It means that their /bin/sh interpreters all work fine with Actually Portable Executable now.
This commit is contained in:
parent
1ae6cfc198
commit
e96aceae41
14 changed files with 512 additions and 11 deletions
1
Makefile
1
Makefile
|
@ -165,6 +165,7 @@ include tool/build/emubin/emubin.mk
|
||||||
include tool/build/build.mk
|
include tool/build/build.mk
|
||||||
include examples/examples.mk
|
include examples/examples.mk
|
||||||
include examples/pyapp/pyapp.mk
|
include examples/pyapp/pyapp.mk
|
||||||
|
include examples/pylife/pylife.mk
|
||||||
include tool/decode/lib/decodelib.mk
|
include tool/decode/lib/decodelib.mk
|
||||||
include tool/decode/decode.mk
|
include tool/decode/decode.mk
|
||||||
include tool/lambda/lib/lib.mk
|
include tool/lambda/lib/lib.mk
|
||||||
|
|
|
@ -223,6 +223,6 @@ gdb foo.com -ex 'add-symbol-file foo.com.dbg 0x401000'
|
||||||
| New Technology | Vista | 2006 |
|
| New Technology | Vista | 2006 |
|
||||||
| GNU/Systemd | 2.6.18 | 2007 |
|
| GNU/Systemd | 2.6.18 | 2007 |
|
||||||
| XNU's Not UNIX! | 15.6 | 2018 |
|
| XNU's Not UNIX! | 15.6 | 2018 |
|
||||||
| FreeBSD | 12 | 2018 |
|
| FreeBSD | 13 | 2020 |
|
||||||
| OpenBSD | 6.4 | 2018 |
|
| OpenBSD | 6.4 | 2018 |
|
||||||
| NetBSD | 9.1 | 2020 |
|
| NetBSD | 9.2 | 2021 |
|
||||||
|
|
|
@ -164,8 +164,34 @@ o/$(MODE)/usr/share/dict/words: \
|
||||||
@$(MKDIR) $(@D)
|
@$(MKDIR) $(@D)
|
||||||
@o/$(MODE)/tool/build/gzip.com $(ZFLAGS) -cd <$< >$@
|
@o/$(MODE)/tool/build/gzip.com $(ZFLAGS) -cd <$< >$@
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# binaries for execve_test.com
|
||||||
|
|
||||||
|
o/$(MODE)/examples/life-nomod.com.zip.o: ZIPOBJ_FLAGS += -B
|
||||||
|
o/$(MODE)/examples/life-classic.com.zip.o: ZIPOBJ_FLAGS += -B
|
||||||
|
o/$(MODE)/examples/pylife/pylife.com.zip.o: ZIPOBJ_FLAGS += -B
|
||||||
|
|
||||||
|
o/$(MODE)/examples/life-classic.com.dbg: \
|
||||||
|
$(EXAMPLES_DEPS) \
|
||||||
|
o/$(MODE)/examples/life.o \
|
||||||
|
o/$(MODE)/examples/examples.pkg \
|
||||||
|
$(CRT) \
|
||||||
|
$(APE)
|
||||||
|
@$(APELINK)
|
||||||
|
|
||||||
|
o/$(MODE)/examples/life-nomod.com.dbg: \
|
||||||
|
$(EXAMPLES_DEPS) \
|
||||||
|
o/$(MODE)/examples/life.o \
|
||||||
|
o/$(MODE)/examples/examples.pkg \
|
||||||
|
$(CRT) \
|
||||||
|
$(APE_NO_MODIFY_SELF)
|
||||||
|
@$(APELINK)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/examples
|
.PHONY: o/$(MODE)/examples
|
||||||
o/$(MODE)/examples: \
|
o/$(MODE)/examples: \
|
||||||
o/$(MODE)/examples/package \
|
o/$(MODE)/examples/package \
|
||||||
|
o/$(MODE)/examples/pylife \
|
||||||
o/$(MODE)/examples/pyapp \
|
o/$(MODE)/examples/pyapp \
|
||||||
$(EXAMPLES_BINS)
|
$(EXAMPLES_BINS)
|
||||||
|
|
116
examples/pylife/pylife.mk
Normal file
116
examples/pylife/pylife.mk
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# Actually Portable Python Tutorial
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# This tutorial demonstrates how to compile Python apps as tiny
|
||||||
|
# static multiplatform APE executables as small as 1.9m in size
|
||||||
|
# using Cosmopolitan, which is a BSD-style multitenant codebase
|
||||||
|
#
|
||||||
|
# GETTING STARTED
|
||||||
|
#
|
||||||
|
# # run these commands after cloning the cosmo repo on linux
|
||||||
|
# $ make -j8 o//examples/pylife/pylife.com
|
||||||
|
# $ o//examples/pylife/pylife.com
|
||||||
|
# cosmopolitan is cool!
|
||||||
|
#
|
||||||
|
# HOW IT WORKS
|
||||||
|
#
|
||||||
|
# $ pyobj.com -m -o pylife.o pylife.py
|
||||||
|
# $ ld -static -nostdlib -T o//ape/ape.lds ape.o crt.o \
|
||||||
|
# pylife.o \
|
||||||
|
# cosmopolitan-python-stage2.a \
|
||||||
|
# cosmopolitan-sqlite3.a \
|
||||||
|
# cosmopolitan-linenoise.a \
|
||||||
|
# cosmopolitan-bzip2.a \
|
||||||
|
# cosmopolitan-python-stage1.a \
|
||||||
|
# cosmopolitan.a
|
||||||
|
# $ ./pylife.com
|
||||||
|
# cosmopolitan is cool!
|
||||||
|
#
|
||||||
|
# NOTES
|
||||||
|
#
|
||||||
|
# If you enjoy this tutorial, let us know jtunney@gmail.com. If
|
||||||
|
# you're building something cool, then we can we can add you to
|
||||||
|
# our .gitowners file which grants you commit access so you can
|
||||||
|
# indepnedently maintain your package, as part of the mono-repo
|
||||||
|
|
||||||
|
PKGS += PYLIFE
|
||||||
|
PYLIFE = $(PYLIFE_DEPS) o/$(MODE)/examples/pylife/pylife.a
|
||||||
|
PYLIFE_COMS = o/$(MODE)/examples/pylife/pylife.com
|
||||||
|
PYLIFE_BINS = $(PYLIFE_COMS) $(PYLIFE_COMS:%=%.dbg)
|
||||||
|
|
||||||
|
# Specify our Cosmopolitan library dependencies
|
||||||
|
#
|
||||||
|
# - THIRD_PARTY_PYTHON_STAGE1 plus THIRD_PARTY_PYTHON_STAGE2 will
|
||||||
|
# define the Python CAPI and supported standard library modules
|
||||||
|
#
|
||||||
|
PYLIFE_DIRECTDEPS = \
|
||||||
|
THIRD_PARTY_PYTHON_STAGE2
|
||||||
|
|
||||||
|
# Compute the transitive closure of dependencies. There's dozens of
|
||||||
|
# other static libraries we need, in order to build a static binary
|
||||||
|
# such as fmt.a, runtime.a, str.a etc. This magic statement figures
|
||||||
|
# them all out and arranges them in the correct order.
|
||||||
|
PYLIFE_DEPS := $(call uniq,$(foreach x,$(PYLIFE_DIRECTDEPS),$($(x))))
|
||||||
|
|
||||||
|
# # Asks PYOBJ.COM to turn our Python source into an ELF object which
|
||||||
|
# # contains (a) embedded zip file artifacts of our .py file and .pyc
|
||||||
|
# # which it it compiled; and (b) statically analyzed listings of our
|
||||||
|
# # python namespaces and imports that GNU ld will use for tree shake
|
||||||
|
# # NOTE: This code can be commented out since it's in build/rules.mk
|
||||||
|
# o/$(MODE)/examples/pylife/pylife.o: examples/pylife/pylife.py o/$(MODE)/third_party/python/pyobj
|
||||||
|
# o/$(MODE)/third_party/python/pyobj $(PYFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
# We need to define how the repository source code path gets mapped
|
||||||
|
# into an APE ZIP file path. By convention, we place Python modules
|
||||||
|
# in `.python/` (which is accessible via open() system calls, using
|
||||||
|
# the synthetic path `"/zip/.python/"`) which means that if we want
|
||||||
|
# to turn `pylife/pylife.py` into `.python/pylife.py` so it's imported
|
||||||
|
# using `import pylife` then we can simply append to PYOBJ.COM flags
|
||||||
|
# flags above asking it to strip one directory component and prefix
|
||||||
|
# Lastly be sure that whenever you use this variable override trick
|
||||||
|
# you only do it to .o files, since otherwise it'll ruin everything
|
||||||
|
# Passing -m to PYOBJ.COM causes a C main() function to get yoinked
|
||||||
|
# and it means our Python module can no longer be used as a library
|
||||||
|
o/$(MODE)/examples/pylife/pylife.o: PYFLAGS += -m -C2 -P.python
|
||||||
|
|
||||||
|
# Asks PACKAGE.COM to sanity check our DIRECTDEPS and symbol graph.
|
||||||
|
# This program functions as an incremental linker. It also provides
|
||||||
|
# enhancements to the object code that GCC generated similar to LTO
|
||||||
|
# so be certain that your .com.dbg rule depends on the .pkg output!
|
||||||
|
o/$(MODE)/examples/pylife/pylife.pkg: \
|
||||||
|
o/$(MODE)/examples/pylife/pylife.o \
|
||||||
|
$(foreach x,$(PYLIFE_DIRECTDEPS),$($(x)_A).pkg)
|
||||||
|
|
||||||
|
# Ask GNU LD to link our APE executable within an ELF binary shell.
|
||||||
|
# The CRT and APE dependencies are special dependencies that define
|
||||||
|
# your _start() / WinMain() entrpoints as well as APE linker script
|
||||||
|
o/$(MODE)/examples/pylife/pylife.com.dbg: \
|
||||||
|
$(PYLIFE_DEPS) \
|
||||||
|
o/$(MODE)/examples/pylife/pylife.pkg \
|
||||||
|
o/$(MODE)/examples/pylife/pylife.o \
|
||||||
|
$(CRT) \
|
||||||
|
$(APE_NO_MODIFY_SELF)
|
||||||
|
$(LINK) $(LINKARGS) -o $@
|
||||||
|
|
||||||
|
# # Unwrap the APE .COM binary, that's embedded within the linked file
|
||||||
|
# # NOTE: This line can be commented out, since it's in build/rules.mk
|
||||||
|
# o/$(MODE)/examples/pylife/pylife.com: \
|
||||||
|
# o/$(MODE)/examples/pylife/pylife.com.dbg
|
||||||
|
# $(OBJCOPY) -S -O binary $< $@
|
||||||
|
|
||||||
|
# Ensure that build config changes will invalidate build artifacts.
|
||||||
|
o/$(MODE)/examples/pylife/pylife.o: \
|
||||||
|
examples/pylife/pylife.mk
|
||||||
|
|
||||||
|
# By convention we want to be able to say `make -j8 o//examples/pylife`
|
||||||
|
# and have it build all targets the package defines.
|
||||||
|
.PHONY: o/$(MODE)/examples/pylife
|
||||||
|
o/$(MODE)/examples/pylife: \
|
||||||
|
o/$(MODE)/examples/pylife/pylife.com \
|
||||||
|
o/$(MODE)/examples/pylife/pylife.com.dbg
|
2
examples/pylife/pylife.py
Normal file
2
examples/pylife/pylife.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
import sys
|
||||||
|
sys.exit(42)
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/mem/alloca.h"
|
#include "libc/mem/alloca.h"
|
||||||
#include "libc/paths.h"
|
#include "libc/paths.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
@ -81,11 +82,7 @@ int sys_execve(const char *prog, char *const argv[], char *const envp[]) {
|
||||||
shargs[2] = prog;
|
shargs[2] = prog;
|
||||||
memcpy(shargs + 3, argv, (i + 1) * sizeof(char *));
|
memcpy(shargs + 3, argv, (i + 1) * sizeof(char *));
|
||||||
} else if (CanExecute(prog)) {
|
} else if (CanExecute(prog)) {
|
||||||
if (IsFreebsd() || IsNetbsd()) {
|
shargs[0] = _PATH_BSHELL;
|
||||||
shargs[0] = firstnonnull(commandv("bash", buf, PATH_MAX), _PATH_BSHELL);
|
|
||||||
} else {
|
|
||||||
shargs[0] = _PATH_BSHELL;
|
|
||||||
}
|
|
||||||
shargs[1] = prog;
|
shargs[1] = prog;
|
||||||
memcpy(shargs + 2, argv + 1, i * sizeof(char *));
|
memcpy(shargs + 2, argv + 1, i * sizeof(char *));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -96,6 +96,7 @@ static textwindows bool IsDirectorySymlink(const char16_t *path) {
|
||||||
|
|
||||||
static textwindows int sys_rmdir_nt(const char16_t *path) {
|
static textwindows int sys_rmdir_nt(const char16_t *path) {
|
||||||
int e, ms;
|
int e, ms;
|
||||||
|
e = errno;
|
||||||
for (ms = 1;; ms *= 2) {
|
for (ms = 1;; ms *= 2) {
|
||||||
if (RemoveDirectory(path)) {
|
if (RemoveDirectory(path)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -108,6 +109,7 @@ static textwindows int sys_rmdir_nt(const char16_t *path) {
|
||||||
* Never could have imagined it'd be this bad.
|
* Never could have imagined it'd be this bad.
|
||||||
*/
|
*/
|
||||||
if (GetLastError() == kNtErrorDirNotEmpty && ms <= 2048) {
|
if (GetLastError() == kNtErrorDirNotEmpty && ms <= 2048) {
|
||||||
|
errno = e;
|
||||||
Sleep(ms);
|
Sleep(ms);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
.text.startup
|
.text.startup
|
||||||
|
|
||||||
// Seventeen byte decompressor.
|
// Thirteen byte decompressor.
|
||||||
//
|
//
|
||||||
// @param di points to output buffer
|
// @param di points to output buffer
|
||||||
// @param si points to uint8_t {len₁,byte₁}, ..., {0,0}
|
// @param si points to uint8_t {len₁,byte₁}, ..., {0,0}
|
||||||
|
@ -32,8 +32,7 @@ rldecode:
|
||||||
xchg %al,%cl
|
xchg %al,%cl
|
||||||
lodsb
|
lodsb
|
||||||
jrcxz 2f
|
jrcxz 2f
|
||||||
1: stosb
|
rep stosb
|
||||||
.loop 1b
|
|
||||||
jmp 0b
|
jmp 0b
|
||||||
2: .leafepilogue
|
2: .leafepilogue
|
||||||
.endfn rldecode,globl
|
.endfn rldecode,globl
|
||||||
|
|
347
test/libc/calls/execve_test.c
Normal file
347
test/libc/calls/execve_test.c
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 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. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/assert.h"
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/mem/io.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
|
#include "libc/testlib/ezbench.h"
|
||||||
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
|
STATIC_YOINK("zip_uri_support");
|
||||||
|
|
||||||
|
int ws, pid;
|
||||||
|
char testlib_enable_tmp_setup_teardown;
|
||||||
|
|
||||||
|
bool UsingBinfmtMisc(void) {
|
||||||
|
return fileexists("/proc/sys/fs/binfmt_misc/APE");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasMzHeader(const char *path) {
|
||||||
|
char buf[2] = {0};
|
||||||
|
open(path, O_RDONLY);
|
||||||
|
read(3, buf, 2);
|
||||||
|
close(3);
|
||||||
|
return buf[0] == 'M' && buf[1] == 'Z';
|
||||||
|
}
|
||||||
|
|
||||||
|
void Extract(const char *from, const char *to, int mode) {
|
||||||
|
ASSERT_SYS(0, 3, open(from, O_RDONLY), "%s %s", from, to);
|
||||||
|
ASSERT_SYS(0, 4, creat(to, mode));
|
||||||
|
ASSERT_NE(-1, _copyfd(3, 4, -1));
|
||||||
|
EXPECT_SYS(0, 0, close(4));
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUp(void) {
|
||||||
|
ASSERT_SYS(0, 0, mkdir("tmp", 0755));
|
||||||
|
ASSERT_SYS(0, 0, mkdir("bin", 0755));
|
||||||
|
Extract("/zip/tiny64.elf", "bin/tiny64.elf", 0755);
|
||||||
|
Extract("/zip/pylife.com", "bin/pylife.com", 0755);
|
||||||
|
Extract("/zip/life-nomod.com", "bin/life-nomod.com", 0755);
|
||||||
|
Extract("/zip/life-classic.com", "bin/life-classic.com", 0755);
|
||||||
|
setenv("TMPDIR", "tmp", true);
|
||||||
|
if (IsOpenbsd()) {
|
||||||
|
// printf is in /usr/bin/printf on openbsd...
|
||||||
|
setenv("PATH", "/bin:/usr/bin", true);
|
||||||
|
} else if (!IsWindows()) {
|
||||||
|
setenv("PATH", "/bin", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TEST(execve, system_elf) {
|
||||||
|
if (!IsLinux()) return;
|
||||||
|
ws = system("bin/tiny64.elf");
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(42, WEXITSTATUS(ws));
|
||||||
|
system("cp bin/tiny64.elf /tmp/tiny64.elf");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(execve, fork_elf) {
|
||||||
|
if (!IsLinux()) return;
|
||||||
|
ASSERT_NE(-1, (pid = fork()));
|
||||||
|
if (!pid) {
|
||||||
|
execl("bin/tiny64.elf", "bin/tiny64.elf", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
ASSERT_EQ(pid, wait(&ws));
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(42, WEXITSTATUS(ws));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(execve, vfork_elf) {
|
||||||
|
if (!IsLinux()) return;
|
||||||
|
ASSERT_NE(-1, (pid = vfork()));
|
||||||
|
if (!pid) {
|
||||||
|
execl("bin/tiny64.elf", "bin/tiny64.elf", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
ASSERT_EQ(pid, wait(&ws));
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(42, WEXITSTATUS(ws));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TEST(execve, system_apeNoModifySelf) {
|
||||||
|
if (IsWindows()) return; // todo(jart): wut
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
ws = system("bin/life-nomod.com");
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(42, WEXITSTATUS(ws));
|
||||||
|
EXPECT_TRUE(HasMzHeader("bin/life-nomod.com"));
|
||||||
|
system("cp bin/life-nomod.com /tmp/life-nomod.com");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(execve, fork_apeNoModifySelf) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
ASSERT_NE(-1, (pid = fork()));
|
||||||
|
if (!pid) {
|
||||||
|
execl("bin/life-nomod.com", "bin/life-nomod.com", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
ASSERT_EQ(pid, wait(&ws));
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(42, WEXITSTATUS(ws));
|
||||||
|
EXPECT_TRUE(HasMzHeader("bin/life-nomod.com"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(execve, vfork_apeNoModifySelf) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
ASSERT_NE(-1, (pid = vfork()));
|
||||||
|
if (!pid) {
|
||||||
|
execl("bin/life-nomod.com", "bin/life-nomod.com", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
ASSERT_EQ(pid, wait(&ws));
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(42, WEXITSTATUS(ws));
|
||||||
|
EXPECT_TRUE(HasMzHeader("bin/life-nomod.com"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TEST(execve, system_apeClassic) {
|
||||||
|
if (IsWindows()) return; // todo(jart): wut
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
system("bin/life-classic.com");
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(42, WEXITSTATUS(ws));
|
||||||
|
if (UsingBinfmtMisc()) {
|
||||||
|
EXPECT_TRUE(HasMzHeader("bin/life-classic.com"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(execve, fork_apeClassic) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
ASSERT_NE(-1, (pid = fork()));
|
||||||
|
if (!pid) {
|
||||||
|
execl("bin/life-classic.com", "bin/life-classic.com", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
ASSERT_EQ(pid, wait(&ws));
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(42, WEXITSTATUS(ws));
|
||||||
|
if (UsingBinfmtMisc()) {
|
||||||
|
EXPECT_TRUE(HasMzHeader("bin/life-classic.com"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(execve, vfork_apeClassic) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
ASSERT_NE(-1, (pid = vfork()));
|
||||||
|
if (!pid) {
|
||||||
|
execl("bin/life-classic.com", "bin/life-classic.com", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
ASSERT_EQ(pid, wait(&ws));
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(42, WEXITSTATUS(ws));
|
||||||
|
if (UsingBinfmtMisc()) {
|
||||||
|
EXPECT_TRUE(HasMzHeader("bin/life-classic.com"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
TEST(execve, system_apeNoMod3mb) {
|
||||||
|
if (IsWindows()) return; // todo(jart): wut
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
system("bin/pylife.com");
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(42, WEXITSTATUS(ws));
|
||||||
|
EXPECT_TRUE(HasMzHeader("bin/pylife.com"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(execve, fork_apeNoMod3mb) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
ASSERT_NE(-1, (pid = fork()));
|
||||||
|
if (!pid) {
|
||||||
|
execl("bin/pylife.com", "bin/pylife.com", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
ASSERT_EQ(pid, wait(&ws));
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(42, WEXITSTATUS(ws));
|
||||||
|
EXPECT_TRUE(HasMzHeader("bin/pylife.com"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(execve, vfork_apeNoMod3mb) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
ASSERT_NE(-1, (pid = vfork()));
|
||||||
|
if (!pid) {
|
||||||
|
execl("bin/pylife.com", "bin/pylife.com", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
ASSERT_EQ(pid, wait(&ws));
|
||||||
|
EXPECT_TRUE(WIFEXITED(ws));
|
||||||
|
EXPECT_EQ(42, WEXITSTATUS(ws));
|
||||||
|
EXPECT_TRUE(HasMzHeader("bin/pylife.com"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void SystemElf(void) {
|
||||||
|
system("bin/tiny64.elf");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ForkElf(void) {
|
||||||
|
if (!fork()) {
|
||||||
|
execl("bin/tiny64.elf", "bin/tiny64.elf", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
wait(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VforkElf(void) {
|
||||||
|
if (!vfork()) {
|
||||||
|
execl("bin/tiny64.elf", "bin/tiny64.elf", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
wait(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void SystemNoMod(void) {
|
||||||
|
system("bin/life-nomod.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ForkNoMod(void) {
|
||||||
|
if (!fork()) {
|
||||||
|
execl("bin/life-nomod.com", "bin/life-nomod.com", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
wait(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VforkNoMod(void) {
|
||||||
|
if (!vfork()) {
|
||||||
|
execl("bin/life-nomod.com", "bin/life-nomod.com", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
wait(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void SystemClassic(void) {
|
||||||
|
system("bin/life-classic.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ForkClassic(void) {
|
||||||
|
if (!fork()) {
|
||||||
|
execl("bin/life-classic.com", "bin/life-classic.com", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
wait(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VforkClassic(void) {
|
||||||
|
if (!vfork()) {
|
||||||
|
execl("bin/life-classic.com", "bin/life-classic.com", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
wait(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void SystemNoMod3mb(void) {
|
||||||
|
system("bin/life-nomod.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ForkNoMod3mb(void) {
|
||||||
|
if (!fork()) {
|
||||||
|
execl("bin/life-nomod.com", "bin/life-nomod.com", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
wait(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VforkNoMod3mb(void) {
|
||||||
|
if (!vfork()) {
|
||||||
|
execl("bin/life-nomod.com", "bin/life-nomod.com", 0);
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
wait(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCH(execve, bench1) {
|
||||||
|
if (IsLinux()) {
|
||||||
|
EZBENCH2("ForkElf", donothing, ForkElf());
|
||||||
|
EZBENCH2("VforkElf", donothing, VforkElf());
|
||||||
|
EZBENCH2("SystemElf", donothing, SystemElf());
|
||||||
|
kprintf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
EZBENCH2("ForkApeClassic", donothing, ForkClassic());
|
||||||
|
EZBENCH2("VforkApeClassic", donothing, VforkClassic());
|
||||||
|
if (!IsWindows()) {
|
||||||
|
EZBENCH2("SystemApeClassic", donothing, SystemClassic());
|
||||||
|
}
|
||||||
|
kprintf("\n");
|
||||||
|
|
||||||
|
EZBENCH2("ForkApeNoMod", donothing, ForkNoMod());
|
||||||
|
EZBENCH2("VforkApeNoMod", donothing, VforkNoMod());
|
||||||
|
if (!IsWindows()) {
|
||||||
|
EZBENCH2("SystemApeNoMod", donothing, SystemNoMod());
|
||||||
|
}
|
||||||
|
kprintf("\n");
|
||||||
|
|
||||||
|
EZBENCH2("ForkNoMod3mb", donothing, ForkNoMod3mb());
|
||||||
|
EZBENCH2("VforkNoMod3mb", donothing, VforkNoMod3mb());
|
||||||
|
if (!IsWindows()) {
|
||||||
|
EZBENCH2("SystemNoMod3mb", donothing, SystemNoMod3mb());
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,6 +57,10 @@ o/$(MODE)/test/libc/calls/calls.pkg: \
|
||||||
o/$(MODE)/test/libc/calls/%.com.dbg: \
|
o/$(MODE)/test/libc/calls/%.com.dbg: \
|
||||||
$(TEST_LIBC_CALLS_DEPS) \
|
$(TEST_LIBC_CALLS_DEPS) \
|
||||||
o/$(MODE)/test/libc/calls/%.o \
|
o/$(MODE)/test/libc/calls/%.o \
|
||||||
|
o/$(MODE)/examples/life-nomod.com.zip.o \
|
||||||
|
o/$(MODE)/examples/life-classic.com.zip.o \
|
||||||
|
o/$(MODE)/examples/pylife/pylife.com.zip.o \
|
||||||
|
o/$(MODE)/test/libc/calls/tiny64.elf.zip.o \
|
||||||
o/$(MODE)/third_party/python/Lib/test/tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt.zip.o \
|
o/$(MODE)/third_party/python/Lib/test/tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt.zip.o \
|
||||||
o/$(MODE)/test/libc/calls/calls.pkg \
|
o/$(MODE)/test/libc/calls/calls.pkg \
|
||||||
$(LIBC_TESTMAIN) \
|
$(LIBC_TESTMAIN) \
|
||||||
|
@ -64,6 +68,8 @@ o/$(MODE)/test/libc/calls/%.com.dbg: \
|
||||||
$(APE_NO_MODIFY_SELF)
|
$(APE_NO_MODIFY_SELF)
|
||||||
@$(APELINK)
|
@$(APELINK)
|
||||||
|
|
||||||
|
o/$(MODE)/test/libc/calls/tiny64.elf.zip.o: ZIPOBJ_FLAGS += -B
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/test/libc/calls
|
.PHONY: o/$(MODE)/test/libc/calls
|
||||||
o/$(MODE)/test/libc/calls: \
|
o/$(MODE)/test/libc/calls: \
|
||||||
$(TEST_LIBC_CALLS_BINS) \
|
$(TEST_LIBC_CALLS_BINS) \
|
||||||
|
|
BIN
test/libc/calls/tiny64.elf
Executable file
BIN
test/libc/calls/tiny64.elf
Executable file
Binary file not shown.
|
@ -37,6 +37,7 @@ TEST(cthread_create, testJoinDeadlock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(cthread_create, testCreateReturnJoin) {
|
TEST(cthread_create, testCreateReturnJoin) {
|
||||||
|
if (IsOpenbsd()) return; // TODO(jart): flakes
|
||||||
void *exitcode;
|
void *exitcode;
|
||||||
cthread_t thread;
|
cthread_t thread;
|
||||||
ASSERT_EQ(0, cthread_create(&thread, 0, ReturnArg, ReturnArg));
|
ASSERT_EQ(0, cthread_create(&thread, 0, ReturnArg, ReturnArg));
|
||||||
|
@ -49,6 +50,7 @@ static void *ExitArg(void *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(cthread_create, testCreateExitJoin) {
|
TEST(cthread_create, testCreateExitJoin) {
|
||||||
|
if (IsOpenbsd()) return; // TODO(jart): flakes
|
||||||
void *exitcode;
|
void *exitcode;
|
||||||
cthread_t thread;
|
cthread_t thread;
|
||||||
ASSERT_EQ(0, cthread_create(&thread, 0, ExitArg, (void *)-31337));
|
ASSERT_EQ(0, cthread_create(&thread, 0, ExitArg, (void *)-31337));
|
||||||
|
@ -59,6 +61,7 @@ TEST(cthread_create, testCreateExitJoin) {
|
||||||
TEST(gcctls, size) {
|
TEST(gcctls, size) {
|
||||||
if (IsXnu()) return; // TODO(jart): codemorph
|
if (IsXnu()) return; // TODO(jart): codemorph
|
||||||
if (IsWindows()) return; // TODO(jart): codemorph
|
if (IsWindows()) return; // TODO(jart): codemorph
|
||||||
|
if (IsOpenbsd()) return; // TODO(jart): flakes
|
||||||
// schlep in .zip section too
|
// schlep in .zip section too
|
||||||
// make sure executable isn't too huge
|
// make sure executable isn't too huge
|
||||||
size_t size;
|
size_t size;
|
||||||
|
@ -84,6 +87,7 @@ static void *TlsWorker(void *arg) {
|
||||||
TEST(gcctls, worksAndIsNonInheritable) {
|
TEST(gcctls, worksAndIsNonInheritable) {
|
||||||
if (IsXnu()) return; // TODO(jart): codemorph
|
if (IsXnu()) return; // TODO(jart): codemorph
|
||||||
if (IsWindows()) return; // TODO(jart): codemorph
|
if (IsWindows()) return; // TODO(jart): codemorph
|
||||||
|
if (IsOpenbsd()) return; // TODO(jart): flakes
|
||||||
void *exitcode;
|
void *exitcode;
|
||||||
cthread_t thread;
|
cthread_t thread;
|
||||||
ASSERT_EQ(tdata, 31337);
|
ASSERT_EQ(tdata, 31337);
|
||||||
|
|
|
@ -595,6 +595,7 @@ int main(int argc, char *argv[]) {
|
||||||
/* hosts list empty */
|
/* hosts list empty */
|
||||||
return 0;
|
return 0;
|
||||||
} else if (argc == 4) {
|
} else if (argc == 4) {
|
||||||
|
/* TODO(jart): this is broken */
|
||||||
/* single host */
|
/* single host */
|
||||||
SetupPresharedKeySsl(MBEDTLS_SSL_IS_CLIENT, GetRunitPsk());
|
SetupPresharedKeySsl(MBEDTLS_SSL_IS_CLIENT, GetRunitPsk());
|
||||||
g_sshport = 22;
|
g_sshport = 22;
|
||||||
|
|
|
@ -557,7 +557,7 @@ void Daemonize(void) {
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
int i;
|
int i;
|
||||||
SetupPresharedKeySsl(MBEDTLS_SSL_IS_SERVER, GetRunitPsk());
|
SetupPresharedKeySsl(MBEDTLS_SSL_IS_SERVER, GetRunitPsk());
|
||||||
__log_level = kLogInfo;
|
__log_level = kLogWarn;
|
||||||
GetOpts(argc, argv);
|
GetOpts(argc, argv);
|
||||||
for (i = 3; i < 16; ++i) close(i);
|
for (i = 3; i < 16; ++i) close(i);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
Loading…
Reference in a new issue