mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 00:02:28 +00:00
Make fixes and improvements
- Document more compiler flags - Expose new __print_maps() api - Better overflow checking in mmap() - Improve the shell example somewhat - Fix minor runtime bugs regarding stacks - Make kill() on fork()+execve()'d children work - Support CLONE_CHILD_CLEARTID for proper joining - Fix recent possible deadlock regression with --ftrace
This commit is contained in:
parent
6e52cba37a
commit
ec2cb88058
68 changed files with 1211 additions and 431 deletions
|
@ -68,57 +68,83 @@ static wontreturn void OnUnrecoverableMmapError(const char *s) {
|
|||
_Exit(199);
|
||||
}
|
||||
|
||||
noasan static bool IsMapped(char *p, size_t n) {
|
||||
return OverlapsImageSpace(p, n) || IsMemtracked(FRAME(p), FRAME(p + (n - 1)));
|
||||
static noasan inline bool OverlapsExistingMapping(char *p, size_t n) {
|
||||
int a, b, i;
|
||||
assert(n > 0);
|
||||
a = FRAME(p);
|
||||
b = FRAME(p + (n - 1));
|
||||
i = FindMemoryInterval(&_mmi, a);
|
||||
if (i < _mmi.i) {
|
||||
if (a <= _mmi.p[i].x && _mmi.p[i].x <= b) return true;
|
||||
if (a <= _mmi.p[i].y && _mmi.p[i].y <= b) return true;
|
||||
if (_mmi.p[i].x <= a && b <= _mmi.p[i].y) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
noasan static bool NeedAutomap(char *p, size_t n) {
|
||||
return !p || OverlapsArenaSpace(p, n) || OverlapsShadowSpace(p, n) ||
|
||||
IsMapped(p, n);
|
||||
}
|
||||
|
||||
noasan static bool ChooseMemoryInterval(int x, int n, int *res) {
|
||||
int i;
|
||||
static noasan bool ChooseMemoryInterval(int x, int n, int align, int *res) {
|
||||
int i, start, end;
|
||||
assert(align > 0);
|
||||
if (_mmi.i) {
|
||||
|
||||
// find the start of the automap memory region
|
||||
i = FindMemoryInterval(&_mmi, x);
|
||||
if (i < _mmi.i) {
|
||||
if (x + n < _mmi.p[i].x) {
|
||||
*res = x;
|
||||
return true;
|
||||
|
||||
// check to see if there's space available before the first entry
|
||||
if (!__builtin_add_overflow(x, align - 1, &start)) {
|
||||
start &= -align;
|
||||
if (!__builtin_add_overflow(start, n - 1, &end)) {
|
||||
if (end < _mmi.p[i].x) {
|
||||
*res = start;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check to see if there's space available between two entries
|
||||
while (++i < _mmi.i) {
|
||||
if (_mmi.p[i].x - _mmi.p[i - 1].y > n) {
|
||||
*res = _mmi.p[i - 1].y + 1;
|
||||
return true;
|
||||
if (!__builtin_add_overflow(_mmi.p[i - 1].y, 1, &start) &&
|
||||
!__builtin_add_overflow(start, align - 1, &start)) {
|
||||
start &= -align;
|
||||
if (!__builtin_add_overflow(start, n - 1, &end)) {
|
||||
if (end < _mmi.p[i].x) {
|
||||
*res = start;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (INT_MAX - _mmi.p[i - 1].y >= n) {
|
||||
*res = _mmi.p[i - 1].y + 1;
|
||||
return true;
|
||||
|
||||
// otherwise append after the last entry if space is available
|
||||
if (!__builtin_add_overflow(_mmi.p[i - 1].y, 1, &start) &&
|
||||
!__builtin_add_overflow(start, align - 1, &start)) {
|
||||
start &= -align;
|
||||
if (!__builtin_add_overflow(start, n - 1, &end)) {
|
||||
*res = start;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
} else {
|
||||
*res = x;
|
||||
return true;
|
||||
// if memtrack is empty, then just assign the requested address
|
||||
// assuming it doesn't overflow
|
||||
if (!__builtin_add_overflow(x, align - 1, &start)) {
|
||||
start &= -align;
|
||||
if (!__builtin_add_overflow(start, n - 1, &end)) {
|
||||
*res = start;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
noasan static bool Automap(int n, int *res) {
|
||||
*res = -1;
|
||||
if (ChooseMemoryInterval(FRAME(kAutomapStart), n, res)) {
|
||||
assert(*res >= FRAME(kAutomapStart));
|
||||
if (*res + n <= FRAME(kAutomapStart + (kAutomapStart - 1))) {
|
||||
return true;
|
||||
} else {
|
||||
STRACE("mmap(%.12p, %p) ENOMEM (automap interval exhausted)", ADDR(*res),
|
||||
ADDR(n + 1));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
STRACE("mmap(%.12p, %p) ENOMEM (automap failed)", ADDR(*res), ADDR(n + 1));
|
||||
return false;
|
||||
}
|
||||
noasan static bool Automap(int count, int align, int *res) {
|
||||
return ChooseMemoryInterval(FRAME(kAutomapStart), count, align, res) &&
|
||||
*res + count <= FRAME(kAutomapStart + (kAutomapSize - 1));
|
||||
}
|
||||
|
||||
noasan static size_t GetMemtrackSize(struct MemoryIntervals *mm) {
|
||||
|
@ -221,21 +247,16 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
|
|||
}
|
||||
#endif
|
||||
char *p = addr;
|
||||
bool needguard;
|
||||
struct DirectMap dm;
|
||||
size_t virtualused, virtualneed;
|
||||
int a, b, i, f, m, n, x;
|
||||
bool needguard, clashes;
|
||||
size_t virtualused, virtualneed;
|
||||
|
||||
if (UNLIKELY(!size)) {
|
||||
STRACE("size=0");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(!IsLegalSize(size))) {
|
||||
STRACE("size isn't 48-bit");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(!IsLegalPointer(p))) {
|
||||
STRACE("p isn't 48-bit");
|
||||
return VIP(einval());
|
||||
|
@ -266,29 +287,28 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
|
|||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(INT64_MAX - size < off)) {
|
||||
STRACE("too large");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(!ALIGNED(off))) {
|
||||
STRACE("p isn't 64kb aligned");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if ((flags & MAP_FIXED_NOREPLACE) && IsMapped(p, size)) {
|
||||
#ifdef SYSDEBUG
|
||||
if (OverlapsImageSpace(p, size)) {
|
||||
STRACE("overlaps image");
|
||||
} else {
|
||||
STRACE("overlaps existing");
|
||||
if (fd == -1) {
|
||||
size = ROUNDUP(size, FRAMESIZE);
|
||||
if (IsWindows()) {
|
||||
prot |= PROT_WRITE; /* kludge */
|
||||
}
|
||||
#endif
|
||||
return VIP(efault());
|
||||
} else if (__isfdkind(fd, kFdZip)) {
|
||||
STRACE("fd is zipos handle");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (__isfdkind(fd, kFdZip)) {
|
||||
STRACE("fd is zipos handle");
|
||||
if (UNLIKELY(!IsLegalSize(size))) {
|
||||
STRACE("size isn't 48-bit");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
if (UNLIKELY(INT64_MAX - size < off)) {
|
||||
STRACE("too large");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
|
@ -301,15 +321,29 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
|
|||
return VIP(enomem());
|
||||
}
|
||||
|
||||
if (fd == -1) {
|
||||
size = ROUNDUP(size, FRAMESIZE);
|
||||
if (IsWindows()) {
|
||||
prot |= PROT_WRITE; /* kludge */
|
||||
}
|
||||
clashes = OverlapsImageSpace(p, size) || OverlapsExistingMapping(p, size);
|
||||
|
||||
if ((flags & MAP_FIXED_NOREPLACE) && clashes) {
|
||||
STRACE("noreplace overlaps existing");
|
||||
return VIP(eexist());
|
||||
}
|
||||
|
||||
if (__builtin_add_overflow((int)(size >> 16), (int)!!(size & (FRAMESIZE - 1)),
|
||||
&n)) {
|
||||
STRACE("memory range overflows");
|
||||
return VIP(einval());
|
||||
}
|
||||
|
||||
// if size is a two power then automap will use it as alignment
|
||||
if (IS2POW(size)) {
|
||||
a = size >> 16;
|
||||
if (!a) {
|
||||
a = 1;
|
||||
}
|
||||
} else {
|
||||
a = 1;
|
||||
}
|
||||
|
||||
n = (int)(size >> 16) + !!(size & (FRAMESIZE - 1));
|
||||
assert(n > 0);
|
||||
f = (flags & ~MAP_FIXED_NOREPLACE) | MAP_FIXED;
|
||||
if (flags & MAP_FIXED) {
|
||||
x = FRAME(p);
|
||||
|
@ -318,10 +352,11 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
|
|||
OnUnrecoverableMmapError("FIXED UNTRACK FAILED");
|
||||
}
|
||||
}
|
||||
} else if (!NeedAutomap(p, size)) {
|
||||
} else if (p && !clashes && !OverlapsArenaSpace(p, size) &&
|
||||
!OverlapsShadowSpace(p, size)) {
|
||||
x = FRAME(p);
|
||||
} else if (!Automap(n, &x)) {
|
||||
STRACE("AUTOMAP OUT OF MEMORY D:");
|
||||
} else if (!Automap(n, a, &x)) {
|
||||
STRACE("automap has no room for %d frames with %d alignment", n, a);
|
||||
return VIP(enomem());
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue