2020-08-25 11:23:25 +00:00
|
|
|
#ifndef COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
|
|
|
|
#define COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
|
Introduce --strace flag for system call tracing
This is similar to the --ftrace (c function call trace) flag, except
it's less noisy since it only logs system calls to stderr. Having this
flag is valuable because (1) system call tracing tells us a lot about
the behavior of complex programs and (2) it's usually very hard to get
system call tracing on various operating systems, e.g. strace, ktrace,
dtruss, truss, nttrace, etc. Especially on Apple platforms where even
with the special boot trick, debuggers still aren't guaranteed to work.
make -j8 o//examples
o//examples/hello.com --strace
This is enabled by default in MODE=, MODE=opt, and MODE=dbg. In MODE=dbg
extra information will be printed.
make -j8 MODE=dbg o/dbg/examples
o/dbg/examples/hello.com --strace |& less
This change also changes:
- Rename IsText() → _istext()
- Rename IsUtf8() → _isutf8()
- Fix madvise() on Windows NT
- Fix empty string case of inet_ntop()
- vfork() wrapper now saves and restores errno
- Update xsigaction() to yoink syscall support
2022-03-19 01:07:28 +00:00
|
|
|
#include "libc/assert.h"
|
2021-01-17 03:18:37 +00:00
|
|
|
#include "libc/dce.h"
|
2022-09-12 11:19:32 +00:00
|
|
|
#include "libc/intrin/midpoint.h"
|
2022-09-10 18:55:39 +00:00
|
|
|
#include "libc/intrin/nopl.internal.h"
|
2021-03-01 07:42:35 +00:00
|
|
|
#include "libc/macros.internal.h"
|
2022-05-23 17:15:53 +00:00
|
|
|
#include "libc/nt/version.h"
|
2021-10-14 00:27:13 +00:00
|
|
|
#include "libc/runtime/stack.h"
|
2021-10-15 02:36:49 +00:00
|
|
|
#include "libc/sysv/consts/ss.h"
|
2022-09-12 11:19:32 +00:00
|
|
|
#include "libc/thread/tls.h"
|
2020-08-25 11:23:25 +00:00
|
|
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
|
|
COSMOPOLITAN_C_START_
|
|
|
|
|
2022-09-12 11:19:32 +00:00
|
|
|
#define kAutomapStart 0x100080040000
|
|
|
|
#define kAutomapSize (kMemtrackStart - kAutomapStart)
|
|
|
|
#define kMemtrackStart 0x1fe7fffc0000
|
|
|
|
#define kMemtrackSize (0x1ffffffc0000 - kMemtrackStart)
|
|
|
|
#define kFixedmapStart 0x300000040000
|
|
|
|
#define kFixedmapSize (0x400000040000 - kFixedmapStart)
|
|
|
|
#define kMemtrackFdsStart 0x6fe000040000
|
|
|
|
#define kMemtrackFdsSize (0x6feffffc0000 - kMemtrackFdsStart)
|
|
|
|
#define kMemtrackZiposStart 0x6fd000040000
|
|
|
|
#define kMemtrackZiposSize (0x6fdffffc0000 - kMemtrackZiposStart)
|
|
|
|
#define kMemtrackNsyncStart 0x6fc000040000
|
|
|
|
#define kMemtrackNsyncSize (0x6fcffffc0000 - kMemtrackNsyncStart)
|
|
|
|
#define kMemtrackGran (!IsAsan() ? FRAMESIZE : FRAMESIZE * 8)
|
2020-08-25 11:23:25 +00:00
|
|
|
|
2021-09-04 20:20:47 +00:00
|
|
|
struct MemoryInterval {
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
long h;
|
2022-05-18 23:41:29 +00:00
|
|
|
long size;
|
2021-09-04 20:20:47 +00:00
|
|
|
int prot;
|
|
|
|
int flags;
|
2022-03-20 15:01:14 +00:00
|
|
|
long offset;
|
2022-04-13 05:11:00 +00:00
|
|
|
bool iscow;
|
|
|
|
bool readonlyfile;
|
2021-09-04 20:20:47 +00:00
|
|
|
};
|
|
|
|
|
2020-08-25 11:23:25 +00:00
|
|
|
struct MemoryIntervals {
|
2022-03-16 20:33:13 +00:00
|
|
|
size_t i, n;
|
2021-09-04 20:20:47 +00:00
|
|
|
struct MemoryInterval *p;
|
|
|
|
struct MemoryInterval s[OPEN_MAX];
|
2020-08-25 11:23:25 +00:00
|
|
|
};
|
|
|
|
|
2021-08-06 21:12:11 +00:00
|
|
|
extern hidden struct MemoryIntervals _mmi;
|
2020-08-25 11:23:25 +00:00
|
|
|
|
2022-06-12 18:47:20 +00:00
|
|
|
void __mmi_lock(void) hidden;
|
|
|
|
void __mmi_unlock(void) hidden;
|
2022-04-23 01:55:28 +00:00
|
|
|
bool IsMemtracked(int, int) hidden;
|
2021-10-14 00:27:13 +00:00
|
|
|
void PrintSystemMappings(int) hidden;
|
2021-08-06 21:12:11 +00:00
|
|
|
bool AreMemoryIntervalsOk(const struct MemoryIntervals *) nosideeffect hidden;
|
|
|
|
void PrintMemoryIntervals(int, const struct MemoryIntervals *) hidden;
|
2022-03-20 15:01:14 +00:00
|
|
|
int TrackMemoryInterval(struct MemoryIntervals *, int, int, long, int, int,
|
2022-04-13 05:11:00 +00:00
|
|
|
bool, bool, long, long) hidden;
|
2020-08-25 11:23:25 +00:00
|
|
|
int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int,
|
2021-08-06 21:12:11 +00:00
|
|
|
void (*)(struct MemoryIntervals *, int, int)) hidden;
|
|
|
|
void ReleaseMemoryNt(struct MemoryIntervals *, int, int) hidden;
|
|
|
|
int UntrackMemoryIntervals(void *, size_t) hidden;
|
2022-05-27 06:17:19 +00:00
|
|
|
size_t GetMemtrackSize(struct MemoryIntervals *);
|
2020-08-25 11:23:25 +00:00
|
|
|
|
2022-06-26 09:58:36 +00:00
|
|
|
#ifdef _NOPL0
|
2022-06-13 02:33:42 +00:00
|
|
|
#define __mmi_lock() _NOPL0("__threadcalls", __mmi_lock)
|
|
|
|
#define __mmi_unlock() _NOPL0("__threadcalls", __mmi_unlock)
|
|
|
|
#else
|
2022-06-12 18:47:20 +00:00
|
|
|
#define __mmi_lock() (__threaded ? __mmi_lock() : 0)
|
|
|
|
#define __mmi_unlock() (__threaded ? __mmi_unlock() : 0)
|
2022-06-13 02:33:42 +00:00
|
|
|
#endif
|
2022-06-12 18:47:20 +00:00
|
|
|
|
2021-10-15 02:36:49 +00:00
|
|
|
#define IsLegalPointer(p) \
|
|
|
|
(-0x800000000000 <= (intptr_t)(p) && (intptr_t)(p) <= 0x7fffffffffff)
|
|
|
|
|
2022-03-16 20:33:13 +00:00
|
|
|
forceinline pureconst bool IsLegalSize(size_t n) {
|
2022-04-15 06:39:48 +00:00
|
|
|
return n <= 0x7fffffffffff;
|
2022-03-16 20:33:13 +00:00
|
|
|
}
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
forceinline pureconst bool IsAutoFrame(int x) {
|
2022-09-12 11:19:32 +00:00
|
|
|
return (int)(kAutomapStart >> 16) <= x &&
|
|
|
|
x <= (int)((kAutomapStart + kAutomapSize - 1) >> 16);
|
2021-10-14 00:27:13 +00:00
|
|
|
}
|
|
|
|
|
2021-10-15 02:36:49 +00:00
|
|
|
forceinline pureconst bool IsMemtrackFrame(int x) {
|
2022-09-12 11:19:32 +00:00
|
|
|
return (int)(kAutomapStart >> 16) <= x &&
|
|
|
|
x <= (int)((kAutomapStart + kAutomapSize - 1) >> 16);
|
2021-10-15 02:36:49 +00:00
|
|
|
}
|
|
|
|
|
2022-09-12 11:19:32 +00:00
|
|
|
forceinline pureconst bool IsGfdsFrame(int x) {
|
|
|
|
return (int)(kMemtrackFdsStart >> 16) <= x &&
|
|
|
|
x <= (int)((kMemtrackFdsStart + kMemtrackFdsSize - 1) >> 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
forceinline pureconst bool IsZiposFrame(int x) {
|
|
|
|
return (int)(kMemtrackZiposStart >> 16) <= x &&
|
|
|
|
x <= (int)((kMemtrackZiposStart + kMemtrackZiposSize - 1) >> 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
forceinline pureconst bool IsNsyncFrame(int x) {
|
|
|
|
return (int)(kMemtrackNsyncStart >> 16) <= x &&
|
|
|
|
x <= (int)((kMemtrackNsyncStart + kMemtrackNsyncSize - 1) >> 16);
|
2021-10-14 00:27:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
forceinline pureconst bool IsShadowFrame(int x) {
|
|
|
|
return 0x7fff <= x && x < 0x10008000;
|
|
|
|
}
|
|
|
|
|
2022-09-12 11:19:32 +00:00
|
|
|
forceinline pureconst bool IsArenaFrame(int x) {
|
|
|
|
return 0x5004 <= x && x <= 0x7ffb;
|
|
|
|
}
|
|
|
|
|
2022-03-16 20:33:13 +00:00
|
|
|
forceinline pureconst bool IsKernelFrame(int x) {
|
2022-07-11 12:55:17 +00:00
|
|
|
intptr_t stack = GetStaticStackAddr(0);
|
2022-05-18 23:41:29 +00:00
|
|
|
return (int)(stack >> 16) <= x &&
|
|
|
|
x <= (int)((stack + (GetStackSize() - FRAMESIZE)) >> 16);
|
2022-03-16 20:33:13 +00:00
|
|
|
}
|
|
|
|
|
2021-10-15 02:36:49 +00:00
|
|
|
forceinline pureconst bool IsStaticStackFrame(int x) {
|
2022-07-11 12:55:17 +00:00
|
|
|
intptr_t stack = GetStaticStackAddr(0);
|
2022-05-18 23:41:29 +00:00
|
|
|
return (int)(stack >> 16) <= x &&
|
|
|
|
x <= (int)((stack + (GetStackSize() - FRAMESIZE)) >> 16);
|
2022-03-16 20:33:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
forceinline pureconst bool IsStackFrame(int x) {
|
2022-07-11 12:55:17 +00:00
|
|
|
intptr_t stack = GetStackAddr();
|
2022-05-18 23:41:29 +00:00
|
|
|
return (int)(stack >> 16) <= x &&
|
|
|
|
x <= (int)((stack + (GetStackSize() - FRAMESIZE)) >> 16);
|
2021-10-14 00:27:13 +00:00
|
|
|
}
|
|
|
|
|
2021-10-15 02:36:49 +00:00
|
|
|
forceinline pureconst bool IsOldStackFrame(int x) {
|
2022-09-12 11:19:32 +00:00
|
|
|
/* openbsd uses 4mb stack by default */
|
|
|
|
/* freebsd uses 512mb stack by default */
|
|
|
|
/* most systems use 8mb stack by default */
|
|
|
|
intptr_t old = ROUNDDOWN(__oldstack, GetStackSize());
|
|
|
|
return (old >> 16) <= x && x <= ((old + (GetStackSize() - FRAMESIZE)) >> 16);
|
2021-10-15 02:36:49 +00:00
|
|
|
}
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
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) {
|
2021-09-28 05:58:51 +00:00
|
|
|
unsigned l, m, r;
|
|
|
|
l = 0;
|
|
|
|
r = mm->i;
|
|
|
|
while (l < r) {
|
2022-05-19 23:57:49 +00:00
|
|
|
m = _midpoint(l, r);
|
2021-09-28 05:58:51 +00:00
|
|
|
if (mm->p[m].y < x) {
|
|
|
|
l = m + 1;
|
|
|
|
} else {
|
|
|
|
r = m;
|
|
|
|
}
|
|
|
|
}
|
Introduce --strace flag for system call tracing
This is similar to the --ftrace (c function call trace) flag, except
it's less noisy since it only logs system calls to stderr. Having this
flag is valuable because (1) system call tracing tells us a lot about
the behavior of complex programs and (2) it's usually very hard to get
system call tracing on various operating systems, e.g. strace, ktrace,
dtruss, truss, nttrace, etc. Especially on Apple platforms where even
with the special boot trick, debuggers still aren't guaranteed to work.
make -j8 o//examples
o//examples/hello.com --strace
This is enabled by default in MODE=, MODE=opt, and MODE=dbg. In MODE=dbg
extra information will be printed.
make -j8 MODE=dbg o/dbg/examples
o/dbg/examples/hello.com --strace |& less
This change also changes:
- Rename IsText() → _istext()
- Rename IsUtf8() → _isutf8()
- Fix madvise() on Windows NT
- Fix empty string case of inet_ntop()
- vfork() wrapper now saves and restores errno
- Update xsigaction() to yoink syscall support
2022-03-19 01:07:28 +00:00
|
|
|
assert(l == mm->i || x <= mm->p[l].y);
|
2021-09-28 05:58:51 +00:00
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
2020-08-25 11:23:25 +00:00
|
|
|
COSMOPOLITAN_C_END_
|
|
|
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
|
|
|
#endif /* COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_ */
|