mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-06 03:08:31 +00:00
Add torture test for zipos file descriptors
This change hardens the code for opening /zip/ files using the system call interface. Thread safety and signal safety has been improved for file descriptors in general. We now document fixed addresses that are needed for low level allocations.
This commit is contained in:
parent
579080cd4c
commit
e466dd0553
44 changed files with 2981 additions and 307 deletions
|
@ -30,6 +30,7 @@
|
|||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/clone.h"
|
||||
|
@ -72,34 +73,6 @@ struct CloneArgs {
|
|||
void *arg;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// THREADING RUNTIME
|
||||
|
||||
static char tibdefault[64];
|
||||
extern int __threadcalls_end[];
|
||||
extern int __threadcalls_start[];
|
||||
|
||||
static privileged dontinline void FixupThreadCalls(void) {
|
||||
/*
|
||||
* _NOPL("__threadcalls", func)
|
||||
*
|
||||
* we have this
|
||||
*
|
||||
* 0f 1f 05 b1 19 00 00 nopl func(%rip)
|
||||
*
|
||||
* we're going to turn it into this
|
||||
*
|
||||
* 67 67 e8 b1 19 00 00 addr32 addr32 call func
|
||||
*/
|
||||
__morph_begin();
|
||||
for (int *p = __threadcalls_start; p < __threadcalls_end; ++p) {
|
||||
_base[*p + 0] = 0x67;
|
||||
_base[*p + 1] = 0x67;
|
||||
_base[*p + 2] = 0xe8;
|
||||
}
|
||||
__morph_end();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// THE NEW TECHNOLOGY
|
||||
|
||||
|
@ -522,12 +495,11 @@ int sys_clone_linux(int flags, char *stk, int *ptid, int *ctid, void *tls,
|
|||
* value from the thread by calling __get_tls(). There are a few
|
||||
* layout expectations imposed by your C library. Those are all
|
||||
* documented by __initialize_tls() which initializes the parts of
|
||||
* the first 64 bytes of tls memory that libc cares about. Also
|
||||
* note that if you decide to use tls once then you must use it
|
||||
* for everything, since this flag also flips a runtime state that
|
||||
* enables it for the main thread and functions such as
|
||||
* __errno_location() will begin assuming they can safely access
|
||||
* the tls segment register.
|
||||
* the first 64 bytes of tls memory that libc cares about. This
|
||||
* flag will transition the C runtime to the `__tls_enabled` state
|
||||
* automatically. If it's used for one thread, then it must be
|
||||
* used for all threads. The first time it's used, it must be used
|
||||
* from the main thread.
|
||||
* @param arg will be passed to your callback
|
||||
* @param tls may be used to set the thread local storage segment;
|
||||
* this parameter is ignored if `CLONE_SETTLS` is not set
|
||||
|
@ -539,30 +511,15 @@ int sys_clone_linux(int flags, char *stk, int *ptid, int *ctid, void *tls,
|
|||
*/
|
||||
int clone(int (*func)(void *), void *stk, size_t stksz, int flags, void *arg,
|
||||
int *ptid, void *tls, size_t tlssz, int *ctid) {
|
||||
int rc, maintid;
|
||||
int rc;
|
||||
struct CloneArgs *wt;
|
||||
|
||||
// transition program to threaded state
|
||||
if (!__threaded && (flags & CLONE_THREAD)) {
|
||||
FixupThreadCalls();
|
||||
}
|
||||
if ((flags & CLONE_SETTLS) && !__tls_enabled) {
|
||||
if (~flags & CLONE_THREAD) {
|
||||
STRACE("clone() tls w/o thread");
|
||||
return einval();
|
||||
}
|
||||
if (__threaded) {
|
||||
STRACE("clone() tls/non-tls mixed order");
|
||||
return einval();
|
||||
}
|
||||
maintid = gettid();
|
||||
__initialize_tls(tibdefault);
|
||||
*(int *)((char *)tibdefault + 0x38) = maintid;
|
||||
*(int *)((char *)tibdefault + 0x3c) = __errno;
|
||||
__install_tls(tibdefault);
|
||||
__threaded = maintid;
|
||||
} else if (flags & CLONE_THREAD) {
|
||||
__threaded = gettid();
|
||||
__enable_tls();
|
||||
}
|
||||
|
||||
if ((flags & CLONE_THREAD) && !__threaded) {
|
||||
__enable_threads();
|
||||
}
|
||||
|
||||
if (!func) {
|
||||
|
|
|
@ -26,6 +26,8 @@ extern unsigned char _tbss_end[];
|
|||
extern unsigned char _tls_size[];
|
||||
|
||||
void _init(void) hidden;
|
||||
void __enable_tls(void) hidden;
|
||||
void __enable_threads(void) hidden;
|
||||
void __restorewintty(void) hidden;
|
||||
void *__cxa_finalize(void *) hidden;
|
||||
void cosmo(int, char **, char **, long (*)[2]) hidden wontreturn;
|
||||
|
|
|
@ -1,249 +0,0 @@
|
|||
/*-*- 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 2020 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/bits/bits.h"
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/directmap.internal.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static void *MoveMemoryIntervals(struct MemoryInterval *d,
|
||||
const struct MemoryInterval *s, int n) {
|
||||
// asan runtime depends on this function
|
||||
int i;
|
||||
assert(n >= 0);
|
||||
if (d > s) {
|
||||
for (i = n; i--;) {
|
||||
d[i] = s[i];
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < n; ++i) {
|
||||
d[i] = s[i];
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
static void RemoveMemoryIntervals(struct MemoryIntervals *mm, int i, int n) {
|
||||
// asan runtime depends on this function
|
||||
assert(i >= 0);
|
||||
assert(i + n <= mm->i);
|
||||
MoveMemoryIntervals(mm->p + i, mm->p + i + n, mm->i - (i + n));
|
||||
mm->i -= n;
|
||||
}
|
||||
|
||||
static bool ExtendMemoryIntervals(struct MemoryIntervals *mm) {
|
||||
int prot, flags;
|
||||
char *base, *shad;
|
||||
size_t gran, size;
|
||||
struct DirectMap dm;
|
||||
gran = kMemtrackGran;
|
||||
base = (char *)kMemtrackStart;
|
||||
prot = PROT_READ | PROT_WRITE;
|
||||
flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED;
|
||||
// TODO(jart): These map handles should not leak across NT fork()
|
||||
if (mm->p == mm->s) {
|
||||
if (IsAsan()) {
|
||||
shad = (char *)(((intptr_t)base >> 3) + 0x7fff8000);
|
||||
dm = sys_mmap(shad, gran >> 3, prot, flags, -1, 0);
|
||||
if (!dm.addr) return false;
|
||||
}
|
||||
dm = sys_mmap(base, gran, prot, flags, -1, 0);
|
||||
if (!dm.addr) return false;
|
||||
MoveMemoryIntervals(dm.addr, mm->p, mm->i);
|
||||
mm->p = dm.addr;
|
||||
mm->n = gran / sizeof(*mm->p);
|
||||
} else {
|
||||
size = ROUNDUP(mm->n * sizeof(*mm->p), gran);
|
||||
base += size;
|
||||
if (IsAsan()) {
|
||||
shad = (char *)(((intptr_t)base >> 3) + 0x7fff8000);
|
||||
dm = sys_mmap(shad, gran >> 3, prot, flags, -1, 0);
|
||||
if (!dm.addr) return false;
|
||||
}
|
||||
dm = sys_mmap(base, gran, prot, flags, -1, 0);
|
||||
if (!dm.addr) return false;
|
||||
mm->n = (size + gran) / sizeof(*mm->p);
|
||||
}
|
||||
#if IsModeDbg()
|
||||
assert(AreMemoryIntervalsOk(mm));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
int CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
|
||||
// asan runtime depends on this function
|
||||
int rc;
|
||||
rc = 0;
|
||||
assert(i >= 0);
|
||||
assert(i <= mm->i);
|
||||
assert(mm->n >= 0);
|
||||
if (UNLIKELY(mm->i == mm->n) && !ExtendMemoryIntervals(mm)) return enomem();
|
||||
MoveMemoryIntervals(mm->p + i + 1, mm->p + i, mm->i++ - i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int PunchHole(struct MemoryIntervals *mm, int x, int y, int i) {
|
||||
if (CreateMemoryInterval(mm, i) == -1) return -1;
|
||||
mm->p[i + 0].size -= (size_t)(mm->p[i + 0].y - (x - 1)) * FRAMESIZE;
|
||||
mm->p[i + 0].y = x - 1;
|
||||
mm->p[i + 1].size -= (size_t)((y + 1) - mm->p[i + 1].x) * FRAMESIZE;
|
||||
mm->p[i + 1].x = y + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
|
||||
void wf(struct MemoryIntervals *, int, int)) {
|
||||
unsigned l, r;
|
||||
#if IsModeDbg()
|
||||
assert(y >= x);
|
||||
assert(AreMemoryIntervalsOk(mm));
|
||||
#endif
|
||||
if (!mm->i) return 0;
|
||||
|
||||
// binary search for the lefthand side
|
||||
l = FindMemoryInterval(mm, x);
|
||||
if (l == mm->i) return 0;
|
||||
if (y < mm->p[l].x) return 0;
|
||||
|
||||
// binary search for the righthand side
|
||||
r = FindMemoryInterval(mm, y);
|
||||
if (r == mm->i || (r > l && y < mm->p[r].x)) --r;
|
||||
assert(r >= l);
|
||||
assert(x <= mm->p[r].y);
|
||||
|
||||
// remove the middle of an existing map
|
||||
//
|
||||
// ----|mmmmmmmmmmmmmmmm|--------- before
|
||||
// xxxxx
|
||||
// ----|mmmm|-----|mmmmm|--------- after
|
||||
//
|
||||
// this isn't possible on windows because we track each
|
||||
// 64kb segment on that platform using a separate entry
|
||||
if (l == r && x > mm->p[l].x && y < mm->p[l].y) {
|
||||
return PunchHole(mm, x, y, l);
|
||||
}
|
||||
|
||||
// trim the right side of the lefthand map
|
||||
//
|
||||
// ----|mmmmmmm|-------------- before
|
||||
// xxxxx
|
||||
// ----|mmmm|----------------- after
|
||||
//
|
||||
if (x > mm->p[l].x && x <= mm->p[l].y) {
|
||||
assert(y >= mm->p[l].y);
|
||||
if (IsWindows()) return einval();
|
||||
mm->p[l].size -= (size_t)(mm->p[l].y - (x - 1)) * FRAMESIZE;
|
||||
mm->p[l].y = x - 1;
|
||||
assert(mm->p[l].x <= mm->p[l].y);
|
||||
++l;
|
||||
}
|
||||
|
||||
// trim the left side of the righthand map
|
||||
//
|
||||
// ------------|mmmmm|-------- before
|
||||
// xxxxx
|
||||
// ---------------|mm|-------- after
|
||||
//
|
||||
if (y >= mm->p[r].x && y < mm->p[r].y) {
|
||||
assert(x <= mm->p[r].x);
|
||||
if (IsWindows()) return einval();
|
||||
mm->p[r].size -= (size_t)((y + 1) - mm->p[r].x) * FRAMESIZE;
|
||||
mm->p[r].x = y + 1;
|
||||
assert(mm->p[r].x <= mm->p[r].y);
|
||||
--r;
|
||||
}
|
||||
|
||||
if (l <= r) {
|
||||
if (IsWindows() && wf) {
|
||||
wf(mm, l, r);
|
||||
}
|
||||
RemoveMemoryIntervals(mm, l, r - l + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h,
|
||||
int prot, int flags, bool readonlyfile, bool iscow,
|
||||
long offset, long size) {
|
||||
// asan runtime depends on this function
|
||||
unsigned i;
|
||||
#if IsModeDbg()
|
||||
assert(y >= x);
|
||||
assert(AreMemoryIntervalsOk(mm));
|
||||
#endif
|
||||
|
||||
i = FindMemoryInterval(mm, x);
|
||||
|
||||
// try to extend the righthand side of the lefthand entry
|
||||
// we can't do that if we're tracking independent handles
|
||||
// we can't do that if it's a file map with a small size!
|
||||
if (i && x == mm->p[i - 1].y + 1 && h == mm->p[i - 1].h &&
|
||||
prot == mm->p[i - 1].prot && flags == mm->p[i - 1].flags &&
|
||||
mm->p[i - 1].size ==
|
||||
(size_t)(mm->p[i - 1].y - mm->p[i - 1].x) * FRAMESIZE + FRAMESIZE) {
|
||||
mm->p[i - 1].size += (size_t)(y - mm->p[i - 1].y) * FRAMESIZE;
|
||||
mm->p[i - 1].y = y;
|
||||
// if we filled the hole then merge the two mappings
|
||||
if (i < mm->i && y + 1 == mm->p[i].x && h == mm->p[i].h &&
|
||||
prot == mm->p[i].prot && flags == mm->p[i].flags) {
|
||||
mm->p[i - 1].y = mm->p[i].y;
|
||||
mm->p[i - 1].size += mm->p[i].size;
|
||||
RemoveMemoryIntervals(mm, i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// try to extend the lefthand side of the righthand entry
|
||||
// we can't do that if we're creating a smaller file map!
|
||||
else if (i < mm->i && y + 1 == mm->p[i].x && h == mm->p[i].h &&
|
||||
prot == mm->p[i].prot && flags == mm->p[i].flags &&
|
||||
size == (size_t)(y - x) * FRAMESIZE + FRAMESIZE) {
|
||||
mm->p[i].size += (size_t)(mm->p[i].x - x) * FRAMESIZE;
|
||||
mm->p[i].x = x;
|
||||
}
|
||||
|
||||
// otherwise, create a new entry and memmove the items
|
||||
else {
|
||||
if (CreateMemoryInterval(mm, i) == -1) return -1;
|
||||
mm->p[i].x = x;
|
||||
mm->p[i].y = y;
|
||||
mm->p[i].h = h;
|
||||
mm->p[i].prot = prot;
|
||||
mm->p[i].flags = flags;
|
||||
mm->p[i].offset = offset;
|
||||
mm->p[i].size = size;
|
||||
mm->p[i].iscow = iscow;
|
||||
mm->p[i].readonlyfile = readonlyfile;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -26,6 +26,10 @@ COSMOPOLITAN_C_START_
|
|||
#define kFixedmapStart _kMem(0x300000000000, 0x000040000000)
|
||||
#define kFixedmapSize \
|
||||
_kMem(0x400000000000 - 0x300000000000, 0x000070000000 - 0x000040000000)
|
||||
#define kMemtrackFdsStart _kMem(0x6fe000000000, 0x80000000)
|
||||
#define kMemtrackFdsSize _kMem(0x001000000000, 0x04000000)
|
||||
#define kMemtrackZiposStart _kMem(0x6fd000000000, 0x84000000)
|
||||
#define kMemtrackZiposSize _kMem(0x001000000000, 0x20000000)
|
||||
#define _kMmi(VSPACE) \
|
||||
ROUNDUP(VSPACE / FRAMESIZE * (intptr_t)sizeof(struct MemoryInterval), \
|
||||
FRAMESIZE)
|
||||
|
|
83
libc/runtime/memtrack32.txt
Normal file
83
libc/runtime/memtrack32.txt
Normal file
|
@ -0,0 +1,83 @@
|
|||
# -*- conf -*-
|
||||
# Cosmopolitan Libc Legacy Memory Plan
|
||||
|
||||
00000000-0000001f 2048kb guard
|
||||
00000020-0000003f 2048kb loader
|
||||
00000040-000000ff 12mb image
|
||||
00000100-000003ff 48mb free
|
||||
00000400-000007ff 64mb free
|
||||
00000800-00000bff 64mb free
|
||||
00000c00-00000fff 64mb free
|
||||
00001000-000013ff 64mb automap
|
||||
00001400-000017ff 64mb automap
|
||||
00001800-00001bff 64mb automap
|
||||
00001c00-00001fff 64mb automap
|
||||
00002000-000023ff 64mb automap
|
||||
00002400-000027ff 64mb automap
|
||||
00002800-00002bff 64mb automap
|
||||
00002c00-00002fff 64mb automap
|
||||
00003000-000033ff 64mb automap
|
||||
00003400-000037ff 64mb automap
|
||||
00003800-00003bff 64mb automap
|
||||
00003c00-00003fe7 63mb automap
|
||||
00003fe4-00003ffb 1536kb memtrack
|
||||
00003ffc-00003fff 256kb free
|
||||
00004000-000043ff 64mb fixedmap
|
||||
00004400-000047ff 64mb fixedmap
|
||||
00004800-00004bff 64mb fixedmap
|
||||
00004c00-00004fff 64mb fixedmap
|
||||
00005000-000053ff 64mb fixedmap
|
||||
00005400-000057ff 64mb fixedmap
|
||||
00005800-00005bff 64mb fixedmap
|
||||
00005c00-00005fff 64mb fixedmap
|
||||
00006000-000063ff 64mb fixedmap
|
||||
00006400-000067ff 64mb fixedmap
|
||||
00006800-00006bff 64mb fixedmap
|
||||
00006c00-00006fff 64mb fixedmap
|
||||
00005000-000053ff 64mb arena
|
||||
00005400-000057ff 64mb arena
|
||||
00005800-00005bff 64mb arena
|
||||
00005c00-00005fff 64mb arena
|
||||
00006000-000063ff 64mb arena
|
||||
00006400-000067ff 64mb arena
|
||||
00006800-00006bff 64mb arena
|
||||
00006c00-00006fff 64mb arena
|
||||
00007000-000073ff 64mb arena
|
||||
00007400-000077ff 64mb arena
|
||||
00007800-00007bff 64mb arena
|
||||
00007c00-00007ffd 64mb arena
|
||||
00007ffe-00007fff 128kb free
|
||||
00008000-000083ff 64mb fds
|
||||
00008400-000087ff 64mb zipos
|
||||
00008800-00008bff 64mb zipos
|
||||
00008c00-00008fff 64mb zipos
|
||||
00009000-000093ff 64mb zipos
|
||||
00009400-000097ff 64mb zipos
|
||||
00009800-00009bff 64mb zipos
|
||||
00009c00-00009fff 64mb zipos
|
||||
0000a000-0000a3ff 64mb zipos
|
||||
0000a400-0000a7ff 64mb free
|
||||
0000a800-0000abff 64mb free
|
||||
0000ac00-0000afff 64mb free
|
||||
0000b000-0000b3ff 64mb free
|
||||
0000b400-0000b7ff 64mb free
|
||||
0000b800-0000bbff 64mb free
|
||||
0000bc00-0000bfff 64mb free
|
||||
0000c000-0000c3ff 64mb free
|
||||
0000c400-0000c7ff 64mb free
|
||||
0000c800-0000cbff 64mb free
|
||||
0000cc00-0000cfff 64mb free
|
||||
0000d000-0000d3ff 64mb free
|
||||
0000d400-0000d7ff 64mb free
|
||||
0000d800-0000dbff 64mb free
|
||||
0000dc00-0000dfff 64mb free
|
||||
0000e000-0000e3ff 64mb free
|
||||
0000e400-0000e7ff 64mb free
|
||||
0000e800-0000ebff 64mb free
|
||||
0000ec00-0000efff 64mb free
|
||||
0000f000-0000f3ff 64mb free
|
||||
0000f400-0000f7ff 64mb free
|
||||
0000f800-0000fbff 64mb free
|
||||
0000fc00-0000fffb 64mb free
|
||||
0000fffc-0000fffd 128kb winargs
|
||||
0000fffe-0000ffff 128kb stack
|
2073
libc/runtime/memtrack64.txt
Normal file
2073
libc/runtime/memtrack64.txt
Normal file
File diff suppressed because it is too large
Load diff
|
@ -100,7 +100,7 @@ extern char ape_stack_align[] __attribute__((__weak__));
|
|||
: "=r"(vAddr) \
|
||||
: "i"(ADDEND)); \
|
||||
} else { \
|
||||
vAddr = 0x10000000; \
|
||||
vAddr = 0x100000000 - GetStackSize(); \
|
||||
} \
|
||||
(void *)vAddr; \
|
||||
})
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ 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 │
|
||||
|
@ -16,36 +16,41 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
|
||||
/* asan runtime depends on this function */
|
||||
int i;
|
||||
for (i = 0; i < mm->i; ++i) {
|
||||
if (mm->p[i].y < mm->p[i].x) {
|
||||
STRACE("AreMemoryIntervalsOk() y should be >= x!");
|
||||
return false;
|
||||
}
|
||||
if (!(mm->p[i].size <=
|
||||
(size_t)(mm->p[i].y - mm->p[i].x) * FRAMESIZE + FRAMESIZE &&
|
||||
mm->p[i].size > (size_t)(mm->p[i].y - mm->p[i].x) * FRAMESIZE)) {
|
||||
STRACE("AreMemoryIntervalsOk() size is wrong!");
|
||||
return false;
|
||||
}
|
||||
if (i) {
|
||||
if (mm->p[i].h != -1 || mm->p[i - 1].h != -1) {
|
||||
if (mm->p[i].x <= mm->p[i - 1].y) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!(mm->p[i - 1].y + 1 <= mm->p[i].x)) {
|
||||
STRACE("AreMemoryIntervalsOk() out of order or overlap!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
static char tibdefault[64];
|
||||
extern int __threadcalls_end[];
|
||||
extern int __threadcalls_start[];
|
||||
|
||||
void __enable_tls(void) {
|
||||
__initialize_tls(tibdefault);
|
||||
*(int *)((char *)tibdefault + 0x38) = gettid();
|
||||
*(int *)((char *)tibdefault + 0x3c) = __errno;
|
||||
__install_tls(tibdefault);
|
||||
}
|
||||
|
||||
privileged void __enable_threads(void) {
|
||||
__threaded = gettid();
|
||||
/*
|
||||
* _NOPL("__threadcalls", func)
|
||||
*
|
||||
* we have this
|
||||
*
|
||||
* 0f 1f 05 b1 19 00 00 nopl func(%rip)
|
||||
*
|
||||
* we're going to turn it into this
|
||||
*
|
||||
* 67 67 e8 b1 19 00 00 addr32 addr32 call func
|
||||
*/
|
||||
__morph_begin();
|
||||
for (int *p = __threadcalls_start; p < __threadcalls_end; ++p) {
|
||||
_base[*p + 0] = 0x67;
|
||||
_base[*p + 1] = 0x67;
|
||||
_base[*p + 2] = 0xe8;
|
||||
}
|
||||
__morph_end();
|
||||
}
|
16
libc/runtime/winargs.internal.h
Normal file
16
libc/runtime/winargs.internal.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_WINARGS_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_WINARGS_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct WinArgs {
|
||||
char *argv[4096];
|
||||
char *envp[4092];
|
||||
intptr_t auxv[2][2];
|
||||
char argblock[ARG_MAX / 2];
|
||||
char envblock[ARG_MAX / 2];
|
||||
};
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_WINARGS_INTERNAL_H_ */
|
|
@ -55,6 +55,7 @@
|
|||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/winargs.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpenc.h"
|
||||
|
@ -81,14 +82,6 @@ __msabi extern typeof(VirtualProtect) *const __imp_VirtualProtect;
|
|||
* TODO: How can we ensure we never overlap with KERNEL32.DLL?
|
||||
*/
|
||||
|
||||
struct WinArgs {
|
||||
char *argv[4096];
|
||||
char *envp[4092];
|
||||
intptr_t auxv[2][2];
|
||||
char argblock[ARG_MAX / 2];
|
||||
char envblock[ARG_MAX / 2];
|
||||
};
|
||||
|
||||
extern uint32_t __winmainpid;
|
||||
extern int64_t __wincrashearly;
|
||||
extern const char kConsoleHandles[3];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue