mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-01 03:53:33 +00:00
0cb6b6ff4b
Now that we have understandable system call tracing on Windows, this change rewrites many of the polyfill internals for that platform, to help things get closer to tip top shape. Support for complex forking scenarios had been in a regressed state for quite some time. Now, it works! Subsequent changes should be able to address the performance.
191 lines
5.9 KiB
C
191 lines
5.9 KiB
C
#ifndef COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
|
|
#define COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
|
|
#include "libc/assert.h"
|
|
#include "libc/dce.h"
|
|
#include "libc/macros.internal.h"
|
|
#include "libc/nt/enum/version.h"
|
|
#include "libc/runtime/runtime.h"
|
|
#include "libc/runtime/stack.h"
|
|
#include "libc/sysv/consts/ss.h"
|
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
COSMOPOLITAN_C_START_
|
|
|
|
#define kAutomapStart _kMem(0x100080000000, 0x000010000000)
|
|
#define kAutomapSize \
|
|
_kMem(0x200000000000 - 0x100080000000 - _kMmi(0x800000000000), \
|
|
0x000040000000 - 0x000010000000 - _kMmi(0x000080000000))
|
|
#define kMemtrackStart \
|
|
(ROUNDDOWN(_kMem(0x200000000000 - _kMmi(0x800000000000), \
|
|
0x000040000000 - _kMmi(0x000080000000)), \
|
|
FRAMESIZE * 8) - \
|
|
0x8000 * 8 /* so frame aligned after adding 0x7fff8000 */)
|
|
#define kMemtrackSize _kMem(_kMmi(0x800000000000), _kMmi(0x000080000000))
|
|
#define kMemtrackGran (!IsAsan() ? FRAMESIZE : FRAMESIZE * 8)
|
|
#define kFixedmapStart _kMem(0x300000000000, 0x000040000000)
|
|
#define kFixedmapSize \
|
|
_kMem(0x400000000000 - 0x300000000000, 0x000070000000 - 0x000040000000)
|
|
#define _kMmi(VSPACE) \
|
|
ROUNDUP(VSPACE / FRAMESIZE * (intptr_t)sizeof(struct MemoryInterval), \
|
|
FRAMESIZE)
|
|
#define _kMem(NORMAL, WIN7) \
|
|
(!(IsWindows() && NtGetVersion() < kNtVersionWindows10) ? NORMAL : WIN7)
|
|
|
|
struct MemoryInterval {
|
|
int x;
|
|
int y;
|
|
long h;
|
|
int prot;
|
|
int flags;
|
|
long offset;
|
|
long size;
|
|
};
|
|
|
|
struct MemoryIntervals {
|
|
size_t i, n;
|
|
struct MemoryInterval *p;
|
|
struct MemoryInterval s[OPEN_MAX];
|
|
};
|
|
|
|
extern hidden struct MemoryIntervals _mmi;
|
|
|
|
const char *DescribeFrame(int);
|
|
void PrintSystemMappings(int) hidden;
|
|
char *DescribeProt(int, char[hasatleast 4]);
|
|
char *DescribeMapping(int, int, char[hasatleast 8]) hidden;
|
|
bool AreMemoryIntervalsOk(const struct MemoryIntervals *) nosideeffect hidden;
|
|
void PrintMemoryIntervals(int, const struct MemoryIntervals *) hidden;
|
|
int TrackMemoryInterval(struct MemoryIntervals *, int, int, long, int, int,
|
|
long, long) hidden;
|
|
int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int,
|
|
void (*)(struct MemoryIntervals *, int, int)) hidden;
|
|
void ReleaseMemoryNt(struct MemoryIntervals *, int, int) hidden;
|
|
int UntrackMemoryIntervals(void *, size_t) hidden;
|
|
|
|
#define IsLegalPointer(p) \
|
|
(-0x800000000000 <= (intptr_t)(p) && (intptr_t)(p) <= 0x7fffffffffff)
|
|
|
|
forceinline pureconst bool IsLegalSize(size_t n) {
|
|
return n <= 0xffffffffffff;
|
|
}
|
|
|
|
forceinline pureconst bool IsAutoFrame(int x) {
|
|
return (kAutomapStart >> 16) <= x &&
|
|
x <= ((kAutomapStart + (kAutomapSize - 1)) >> 16);
|
|
}
|
|
|
|
forceinline pureconst bool IsMemtrackFrame(int x) {
|
|
return (kAutomapStart >> 16) <= x &&
|
|
x <= ((kAutomapStart + (kAutomapSize - 1)) >> 16);
|
|
}
|
|
|
|
forceinline pureconst bool IsArenaFrame(int x) {
|
|
return 0x5000 <= x && x < 0x7ffe;
|
|
}
|
|
|
|
forceinline pureconst bool IsShadowFrame(int x) {
|
|
return 0x7fff <= x && x < 0x10008000;
|
|
}
|
|
|
|
forceinline pureconst bool IsKernelFrame(int x) {
|
|
return (int)(GetStaticStackAddr(0) >> 16) <= x &&
|
|
x <= (int)((GetStaticStackAddr(0) + (GetStackSize() - FRAMESIZE)) >>
|
|
16);
|
|
}
|
|
|
|
forceinline pureconst bool IsStaticStackFrame(int x) {
|
|
return (int)(GetStaticStackAddr(0) >> 16) <= x &&
|
|
x <= (int)((GetStaticStackAddr(0) + (GetStackSize() - FRAMESIZE)) >>
|
|
16);
|
|
}
|
|
|
|
forceinline pureconst bool IsStackFrame(int x) {
|
|
return (int)(GetStackAddr(0) >> 16) <= x &&
|
|
x <= (int)((GetStackAddr(0) + (GetStackSize() - FRAMESIZE)) >> 16);
|
|
}
|
|
|
|
forceinline pureconst bool IsSigAltStackFrame(int x) {
|
|
return (int)(GetStackAddr(0) >> 16) <= x &&
|
|
x <= (int)((GetStackAddr(0) + (SIGSTKSZ - FRAMESIZE)) >> 16);
|
|
}
|
|
|
|
forceinline pureconst bool IsOldStackFrame(int x) {
|
|
intptr_t old = ROUNDDOWN(__oldstack, STACKSIZE);
|
|
return (old >> 16) <= x && x <= ((old + (STACKSIZE - FRAMESIZE)) >> 16);
|
|
}
|
|
|
|
forceinline pureconst bool IsFixedFrame(int x) {
|
|
return (kFixedmapStart >> 16) <= x &&
|
|
x <= ((kFixedmapStart + (kFixedmapSize - 1)) >> 16);
|
|
}
|
|
|
|
forceinline pureconst bool OverlapsImageSpace(const void *p, size_t n) {
|
|
const unsigned char *start, *ender;
|
|
if (n) {
|
|
start = p;
|
|
ender = start + (n - 1);
|
|
return ((_base <= start && start < _end) ||
|
|
(_base <= ender && ender < _end) ||
|
|
(start < _base && _end <= ender));
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
forceinline pureconst bool OverlapsArenaSpace(const void *p, size_t n) {
|
|
intptr_t x, y;
|
|
if (n) {
|
|
x = (intptr_t)p;
|
|
y = x + (n - 1);
|
|
return ((0x50000000 <= x && x <= 0x7ffdffff) ||
|
|
(0x50000000 <= y && y <= 0x7ffdffff) ||
|
|
(x < 0x50000000 && 0x7ffdffff < y));
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
forceinline pureconst bool OverlapsShadowSpace(const void *p, size_t n) {
|
|
intptr_t x, y;
|
|
if (n) {
|
|
x = (intptr_t)p;
|
|
y = x + (n - 1);
|
|
return ((0x7fff0000 <= x && x <= 0x10007fffffff) ||
|
|
(0x7fff0000 <= y && y <= 0x10007fffffff) ||
|
|
(x < 0x7fff0000 && 0x10007fffffff < y));
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
forceinline unsigned FindMemoryInterval(const struct MemoryIntervals *mm,
|
|
int x) {
|
|
unsigned l, m, r;
|
|
l = 0;
|
|
r = mm->i;
|
|
while (l < r) {
|
|
m = (l + r) >> 1;
|
|
if (mm->p[m].y < x) {
|
|
l = m + 1;
|
|
} else {
|
|
r = m;
|
|
}
|
|
}
|
|
assert(l == mm->i || x <= mm->p[l].y);
|
|
return l;
|
|
}
|
|
|
|
forceinline bool IsMemtracked(int x, int y) {
|
|
unsigned i;
|
|
i = FindMemoryInterval(&_mmi, x);
|
|
if (i == _mmi.i) return false;
|
|
if (x < _mmi.p[i].x) return false;
|
|
for (;;) {
|
|
if (y <= _mmi.p[i].y) return true;
|
|
if (++i == _mmi.i) return false;
|
|
if (_mmi.p[i].x != _mmi.p[i - 1].y + 1) return false;
|
|
}
|
|
}
|
|
|
|
COSMOPOLITAN_C_END_
|
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
|
#endif /* COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_ */
|