mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-27 15:52:28 +00:00
Mint APE Loader v1.5
This change ports APE Loader to Linux AARCH64, so that Raspberry Pi users can run programs like redbean, without the executable needing to modify itself. Progress has also slipped into this change on the issue of making progress better conforming to user expectations and industry standards regarding which symbols we're allowed to declare
This commit is contained in:
parent
6843150e0c
commit
7e0a09feec
510 changed files with 1783 additions and 1483 deletions
|
@ -27,7 +27,7 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
STATIC_YOINK("realloc");
|
||||
__static_yoink("realloc");
|
||||
|
||||
TEST(grow, testNull_hasAllocatingBehavior) {
|
||||
void *p = NULL;
|
||||
|
|
|
@ -50,128 +50,128 @@ void SetUp(void) {
|
|||
/* 32-BIT SIGNED NEGATION */
|
||||
|
||||
TEST(__negvsi2, testMax) {
|
||||
EXPECT_EQ(-INT_MAX, -VEIL("r", INT_MAX));
|
||||
EXPECT_EQ(-INT_MAX, -__veil("r", INT_MAX));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__negvsi2, testMin0) {
|
||||
EXPROPRIATE(-VEIL("r", INT_MIN));
|
||||
__expropriate(-__veil("r", INT_MIN));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
/* 64-BIT SIGNED NEGATION */
|
||||
|
||||
TEST(__negvdi2, testMax) {
|
||||
EXPECT_EQ(-LONG_MAX, -VEIL("r", LONG_MAX));
|
||||
EXPECT_EQ(-LONG_MAX, -__veil("r", LONG_MAX));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__negvdi2, testMin0) {
|
||||
EXPROPRIATE(-VEIL("r", LONG_MIN));
|
||||
__expropriate(-__veil("r", LONG_MIN));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
/* 32-BIT SIGNED MULTIPLICATION */
|
||||
|
||||
TEST(__mulvsi3, testMin0) {
|
||||
EXPECT_EQ(0, 0 * VEIL("r", INT_MIN));
|
||||
EXPECT_EQ(0, 0 * __veil("r", INT_MIN));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, testMin1) {
|
||||
EXPECT_EQ(INT_MIN, 1 * VEIL("r", INT_MIN));
|
||||
EXPECT_EQ(INT_MIN, 1 * __veil("r", INT_MIN));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, testMin2) {
|
||||
EXPROPRIATE(2 * VEIL("r", INT_MIN));
|
||||
__expropriate(2 * __veil("r", INT_MIN));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, testMax0) {
|
||||
EXPECT_EQ(0, 0 * VEIL("r", INT_MAX));
|
||||
EXPECT_EQ(0, 0 * __veil("r", INT_MAX));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, testMax1) {
|
||||
EXPECT_EQ(INT_MAX, 1 * VEIL("r", INT_MAX));
|
||||
EXPECT_EQ(INT_MAX, 1 * __veil("r", INT_MAX));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, testMax2) {
|
||||
EXPROPRIATE(2 * VEIL("r", INT_MAX));
|
||||
__expropriate(2 * __veil("r", INT_MAX));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, test7) {
|
||||
EXPECT_EQ(0x70000000, 7 * VEIL("r", 0x10000000));
|
||||
EXPECT_EQ(0x70000000, 7 * __veil("r", 0x10000000));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, test8) {
|
||||
EXPROPRIATE(8 * VEIL("r", 0x10000000));
|
||||
__expropriate(8 * __veil("r", 0x10000000));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, test31337) {
|
||||
EXPROPRIATE(0x31337 * VEIL("r", 0x31337));
|
||||
__expropriate(0x31337 * __veil("r", 0x31337));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvsi3, standAndDeliver_aNegativeTimesANegativeEqualsAPositive) {
|
||||
EXPECT_EQ(25, -5 * VEIL("r", -5));
|
||||
EXPECT_EQ(25, -5 * __veil("r", -5));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
/* 64-BIT SIGNED MULTIPLICATION */
|
||||
|
||||
TEST(__mulvdi3, testMin0) {
|
||||
EXPECT_EQ(0, 0 * VEIL("r", LONG_MIN));
|
||||
EXPECT_EQ(0, 0 * __veil("r", LONG_MIN));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, testMin1) {
|
||||
EXPECT_EQ(LONG_MIN, 1 * VEIL("r", LONG_MIN));
|
||||
EXPECT_EQ(LONG_MIN, 1 * __veil("r", LONG_MIN));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, testMin2) {
|
||||
EXPROPRIATE(2 * VEIL("r", LONG_MIN));
|
||||
__expropriate(2 * __veil("r", LONG_MIN));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, testMax0) {
|
||||
EXPECT_EQ(0, 0 * VEIL("r", LONG_MAX));
|
||||
EXPECT_EQ(0, 0 * __veil("r", LONG_MAX));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, testMax1) {
|
||||
EXPECT_EQ(LONG_MAX, 1 * VEIL("r", LONG_MAX));
|
||||
EXPECT_EQ(LONG_MAX, 1 * __veil("r", LONG_MAX));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, testMax2) {
|
||||
EXPROPRIATE(2 * VEIL("r", LONG_MAX));
|
||||
__expropriate(2 * __veil("r", LONG_MAX));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, test7) {
|
||||
EXPECT_EQ(0x7000000000000000l, 7 * VEIL("r", 0x1000000000000000l));
|
||||
EXPECT_EQ(0x7000000000000000l, 7 * __veil("r", 0x1000000000000000l));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, test8) {
|
||||
EXPROPRIATE(8 * VEIL("r", 0x1000000000000000l));
|
||||
__expropriate(8 * __veil("r", 0x1000000000000000l));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, test31337) {
|
||||
EXPROPRIATE(0x3133700000000l * VEIL("r", 0x3133700000000l));
|
||||
__expropriate(0x3133700000000l * __veil("r", 0x3133700000000l));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__mulvdi3, standAndDeliver_aNegativeTimesANegativeEqualsAPositive) {
|
||||
EXPECT_EQ(25l, -5l * VEIL("r", -5l));
|
||||
EXPECT_EQ(25l, -5l * __veil("r", -5l));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
|
@ -188,73 +188,73 @@ TEST(__mulvdi3, testOverflow) {
|
|||
/* 32-BIT SIGNED ADDITION */
|
||||
|
||||
TEST(__addvsi3, testMin1) {
|
||||
EXPECT_EQ(INT_MIN + 1, 1 + VEIL("r", INT_MIN));
|
||||
EXPECT_EQ(INT_MIN + 1, 1 + __veil("r", INT_MIN));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__addvsi3, testMax1) {
|
||||
EXPROPRIATE(1 + VEIL("r", INT_MAX));
|
||||
__expropriate(1 + __veil("r", INT_MAX));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__addvsi3, testNegPos) {
|
||||
EXPECT_EQ(2, -2 + VEIL("r", 4));
|
||||
EXPECT_EQ(2, -2 + __veil("r", 4));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__addvsi3, testPosNeg) {
|
||||
EXPECT_EQ(-2, 2 + VEIL("r", -4));
|
||||
EXPECT_EQ(-2, 2 + __veil("r", -4));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
/* 64-BIT SIGNED ADDITION */
|
||||
|
||||
TEST(__addvdi3, testMin1) {
|
||||
EXPECT_EQ(LONG_MIN + 1, 1 + VEIL("r", LONG_MIN));
|
||||
EXPECT_EQ(LONG_MIN + 1, 1 + __veil("r", LONG_MIN));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__addvdi3, testMax1) {
|
||||
EXPROPRIATE(1 + VEIL("r", LONG_MAX));
|
||||
__expropriate(1 + __veil("r", LONG_MAX));
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__addvdi3, testNegPos) {
|
||||
EXPECT_EQ(2l, -2l + VEIL("r", 4l));
|
||||
EXPECT_EQ(2l, -2l + __veil("r", 4l));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__addvdi3, testPosNeg) {
|
||||
EXPECT_EQ(-2l, 2l + VEIL("r", -4l));
|
||||
EXPECT_EQ(-2l, 2l + __veil("r", -4l));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
/* 32-BIT SIGNED SUBTRACTION */
|
||||
|
||||
TEST(__subvsi3, testMin1) {
|
||||
EXPROPRIATE(VEIL("r", INT_MIN) - 1);
|
||||
__expropriate(__veil("r", INT_MIN) - 1);
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__subvsi3, testMax1) {
|
||||
EXPECT_EQ(INT_MAX - 1, VEIL("r", INT_MAX) - 1);
|
||||
EXPECT_EQ(INT_MAX - 1, __veil("r", INT_MAX) - 1);
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__subvsi3, testPosNeg) {
|
||||
EXPECT_EQ(-2, 2 - VEIL("r", 4));
|
||||
EXPECT_EQ(-2, 2 - __veil("r", 4));
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
/* 64-BIT SIGNED SUBTRACTION */
|
||||
|
||||
TEST(__subvdi3, testMin1) {
|
||||
EXPROPRIATE(VEIL("r", LONG_MIN) - 1);
|
||||
__expropriate(__veil("r", LONG_MIN) - 1);
|
||||
EXPECT_TRUE(overflowed_);
|
||||
}
|
||||
|
||||
TEST(__subvdi3, testMax1) {
|
||||
EXPECT_EQ(LONG_MAX - 1, VEIL("r", LONG_MAX) - 1);
|
||||
EXPECT_EQ(LONG_MAX - 1, __veil("r", LONG_MAX) - 1);
|
||||
EXPECT_FALSE(overflowed_);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
#include "libc/x/xspawn.h"
|
||||
#include "third_party/xed/x86.h"
|
||||
|
||||
STATIC_YOINK("zipos");
|
||||
__static_yoink("zipos");
|
||||
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
@ -116,9 +117,9 @@ void TearDown(void) {
|
|||
}
|
||||
|
||||
TEST(mprotect, testOkMemory) {
|
||||
char *p = gc(memalign(APE_GUARDSIZE, APE_GUARDSIZE));
|
||||
char *p = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
|
||||
p[0] = 0;
|
||||
ASSERT_NE(-1, mprotect(p, APE_GUARDSIZE, PROT_READ | PROT_WRITE));
|
||||
ASSERT_NE(-1, mprotect(p, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE));
|
||||
p[0] = 1;
|
||||
EXPECT_EQ(1, p[0]);
|
||||
EXPECT_FALSE(gotsegv);
|
||||
|
@ -127,19 +128,19 @@ TEST(mprotect, testOkMemory) {
|
|||
|
||||
TEST(mprotect, testSegfault_writeToReadOnlyAnonymous) {
|
||||
volatile char *p;
|
||||
p = gc(memalign(APE_GUARDSIZE, APE_GUARDSIZE));
|
||||
p = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
|
||||
EXPECT_FALSE(gotsegv);
|
||||
p[0] = 1;
|
||||
EXPECT_FALSE(gotsegv);
|
||||
EXPECT_FALSE(gotbusted);
|
||||
EXPECT_NE(-1, mprotect(p, APE_GUARDSIZE, PROT_READ));
|
||||
EXPECT_NE(-1, mprotect(p, getauxval(AT_PAGESZ), PROT_READ));
|
||||
_missingno(p[0]);
|
||||
EXPECT_FALSE(gotsegv);
|
||||
EXPECT_FALSE(gotbusted);
|
||||
p[0] = 2;
|
||||
EXPECT_TRUE(gotsegv | gotbusted);
|
||||
EXPECT_EQ(1, p[0]);
|
||||
EXPECT_NE(-1, mprotect(p, APE_GUARDSIZE, PROT_READ | PROT_WRITE));
|
||||
EXPECT_NE(-1, mprotect(p, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE));
|
||||
}
|
||||
|
||||
TEST(mprotect, testExecOnly_canExecute) {
|
||||
|
@ -159,33 +160,34 @@ TEST(mprotect, testExecOnly_canExecute) {
|
|||
|
||||
TEST(mprotect, testProtNone_cantEvenRead) {
|
||||
volatile char *p;
|
||||
p = gc(memalign(APE_GUARDSIZE, APE_GUARDSIZE));
|
||||
EXPECT_NE(-1, mprotect(p, APE_GUARDSIZE, PROT_NONE));
|
||||
p = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
|
||||
EXPECT_NE(-1, mprotect(p, getauxval(AT_PAGESZ), PROT_NONE));
|
||||
_missingno(p[0]);
|
||||
EXPECT_TRUE(gotsegv | gotbusted);
|
||||
EXPECT_NE(-1, mprotect(p, APE_GUARDSIZE, PROT_READ | PROT_WRITE));
|
||||
EXPECT_NE(-1, mprotect(p, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE));
|
||||
}
|
||||
|
||||
TEST(mprotect, testExecJit_actuallyWorks) {
|
||||
int (*p)(void) = gc(memalign(APE_GUARDSIZE, APE_GUARDSIZE));
|
||||
int (*p)(void) = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
|
||||
memcpy(p, kRet31337, sizeof(kRet31337));
|
||||
EXPECT_NE(-1, mprotect(p, APE_GUARDSIZE, PROT_EXEC));
|
||||
EXPECT_NE(-1, mprotect(p, getauxval(AT_PAGESZ), PROT_EXEC));
|
||||
EXPECT_EQ(31337, p());
|
||||
EXPECT_FALSE(gotsegv);
|
||||
EXPECT_FALSE(gotbusted);
|
||||
EXPECT_NE(-1, mprotect(p, APE_GUARDSIZE, PROT_READ | PROT_WRITE));
|
||||
EXPECT_NE(-1, mprotect(p, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE));
|
||||
}
|
||||
|
||||
TEST(mprotect, testRwxMap_vonNeumannRules) {
|
||||
if (IsOpenbsd()) return; // boo
|
||||
if (IsXnuSilicon()) return; // boo
|
||||
int (*p)(void) = gc(memalign(APE_GUARDSIZE, APE_GUARDSIZE));
|
||||
int (*p)(void) = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
|
||||
memcpy(p, kRet31337, sizeof(kRet31337));
|
||||
EXPECT_NE(-1, mprotect(p, APE_GUARDSIZE, PROT_READ | PROT_WRITE | PROT_EXEC));
|
||||
EXPECT_NE(-1, mprotect(p, getauxval(AT_PAGESZ),
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC));
|
||||
EXPECT_EQ(31337, p());
|
||||
EXPECT_FALSE(gotsegv);
|
||||
EXPECT_FALSE(gotbusted);
|
||||
EXPECT_NE(-1, mprotect(p, APE_GUARDSIZE, PROT_READ | PROT_WRITE));
|
||||
EXPECT_NE(-1, mprotect(p, getauxval(AT_PAGESZ), PROT_READ | PROT_WRITE));
|
||||
}
|
||||
|
||||
TEST(mprotect, testExecuteFlatFileMapOpenedAsReadonly) {
|
||||
|
@ -220,13 +222,13 @@ TEST(mprotect, testFileMap_canChangeToExecWhileOpenInRdwrMode) {
|
|||
}
|
||||
|
||||
TEST(mprotect, testBadProt_failsEinval) {
|
||||
volatile char *p = gc(memalign(APE_GUARDSIZE, APE_GUARDSIZE));
|
||||
volatile char *p = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
|
||||
EXPECT_EQ(-1, mprotect(p, 9999, -1));
|
||||
EXPECT_EQ(EINVAL, errno);
|
||||
}
|
||||
|
||||
TEST(mprotect, testZeroSize_doesNothing) {
|
||||
volatile char *p = gc(memalign(APE_GUARDSIZE, APE_GUARDSIZE));
|
||||
volatile char *p = gc(memalign(getauxval(AT_PAGESZ), getauxval(AT_PAGESZ)));
|
||||
EXPECT_NE(-1, mprotect(p, 0, PROT_READ));
|
||||
p[0] = 1;
|
||||
EXPECT_FALSE(gotsegv);
|
||||
|
|
|
@ -82,10 +82,15 @@ o/$(MODE)/test/libc/runtime/itsatrap_test.o: private \
|
|||
-fno-sanitize=all \
|
||||
-ftrapv
|
||||
|
||||
ifeq ($(ARCH), aarch64)
|
||||
FTRACEASM_LDSCRIPT = o/$(MODE)/ape/aarch64.lds
|
||||
endif
|
||||
|
||||
o/$(MODE)/test/libc/runtime/prog/ftraceasm.elf: \
|
||||
$(TEST_LIBC_RUNTIME_DEPS) \
|
||||
o/$(MODE)/test/libc/runtime/prog/ftraceasm.o \
|
||||
o/$(MODE)/test/libc/runtime/runtime.pkg
|
||||
o/$(MODE)/test/libc/runtime/runtime.pkg \
|
||||
$(FTRACEASM_LDSCRIPT)
|
||||
@$(ELFLINK)
|
||||
o/$(MODE)/test/libc/runtime/prog/ftraceasm.txt: \
|
||||
o/$(MODE)/test/libc/runtime/prog/ftraceasm.elf
|
||||
|
|
|
@ -30,7 +30,7 @@ _Thread_local long x;
|
|||
_Thread_local long y[1] = {40};
|
||||
_Alignas(A) _Thread_local long a;
|
||||
|
||||
noubsan void *Worker(void *arg) {
|
||||
dontubsan void *Worker(void *arg) {
|
||||
ASSERT_EQ(42, x + y[0] + z);
|
||||
ASSERT_EQ(0, (intptr_t)&a & (A - 1));
|
||||
if (IsAsan()) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue