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"
|
2022-05-19 23:57:49 +00:00
|
|
|
#include "libc/bits/midpoint.h"
|
2021-01-17 03:18:37 +00:00
|
|
|
#include "libc/dce.h"
|
2022-06-11 08:59:26 +00:00
|
|
|
#include "libc/intrin/pthread.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"
|
2020-08-25 11:23:25 +00:00
|
|
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
|
|
COSMOPOLITAN_C_START_
|
|
|
|
|
2021-10-15 02:36:49 +00:00
|
|
|
#define kAutomapStart _kMem(0x100080000000, 0x000010000000)
|
|
|
|
#define kAutomapSize \
|
|
|
|
_kMem(0x200000000000 - 0x100080000000 - _kMmi(0x800000000000), \
|
|
|
|
0x000040000000 - 0x000010000000 - _kMmi(0x000080000000))
|
2022-03-20 15:01:14 +00:00
|
|
|
#define kMemtrackStart \
|
|
|
|
(ROUNDDOWN(_kMem(0x200000000000 - _kMmi(0x800000000000), \
|
|
|
|
0x000040000000 - _kMmi(0x000080000000)), \
|
|
|
|
FRAMESIZE * 8) - \
|
|
|
|
0x8000 * 8 /* so frame aligned after adding 0x7fff8000 */)
|
2021-10-15 02:36:49 +00:00
|
|
|
#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)
|
2022-03-16 20:33:13 +00:00
|
|
|
#define _kMmi(VSPACE) \
|
|
|
|
ROUNDUP(VSPACE / FRAMESIZE * (intptr_t)sizeof(struct MemoryInterval), \
|
|
|
|
FRAMESIZE)
|
2021-10-15 02:36:49 +00:00
|
|
|
#define _kMem(NORMAL, WIN7) \
|
2022-05-23 17:15:53 +00:00
|
|
|
(!IsWindows() || IsAtLeastWindows10() ? NORMAL : WIN7)
|
2020-08-25 11:23:25 +00:00
|
|
|
|
2022-06-11 08:59:26 +00:00
|
|
|
#define __mmi_lock() pthread_mutex_lock(&_mmi.lock)
|
|
|
|
#define __mmi_unlock() pthread_mutex_unlock(&_mmi.lock)
|
|
|
|
|
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];
|
2022-06-11 08:59:26 +00:00
|
|
|
pthread_mutex_t lock;
|
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-04-23 01:55:28 +00:00
|
|
|
bool IsMemtracked(int, int) hidden;
|
2021-10-14 00:27:13 +00:00
|
|
|
void PrintSystemMappings(int) hidden;
|
2022-04-23 01:55:28 +00:00
|
|
|
const char *DescribeFrame(int) hidden;
|
2021-10-14 00:27:13 +00:00
|
|
|
char *DescribeMapping(int, int, char[hasatleast 8]) 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
|
|
|
|
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) {
|
|
|
|
return (kAutomapStart >> 16) <= x &&
|
|
|
|
x <= ((kAutomapStart + (kAutomapSize - 1)) >> 16);
|
|
|
|
}
|
|
|
|
|
2021-10-15 02:36:49 +00:00
|
|
|
forceinline pureconst bool IsMemtrackFrame(int x) {
|
|
|
|
return (kAutomapStart >> 16) <= x &&
|
|
|
|
x <= ((kAutomapStart + (kAutomapSize - 1)) >> 16);
|
|
|
|
}
|
|
|
|
|
2021-10-14 00:27:13 +00:00
|
|
|
forceinline pureconst bool IsArenaFrame(int x) {
|
|
|
|
return 0x5000 <= x && x < 0x7ffe;
|
|
|
|
}
|
|
|
|
|
|
|
|
forceinline pureconst bool IsShadowFrame(int x) {
|
|
|
|
return 0x7fff <= x && x < 0x10008000;
|
|
|
|
}
|
|
|
|
|
2022-03-16 20:33:13 +00:00
|
|
|
forceinline pureconst bool IsKernelFrame(int x) {
|
2022-05-18 23:41:29 +00:00
|
|
|
intptr_t stack = (intptr_t)GetStaticStackAddr(0);
|
|
|
|
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-05-18 23:41:29 +00:00
|
|
|
intptr_t stack = (intptr_t)GetStaticStackAddr(0);
|
|
|
|
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-05-18 23:41:29 +00:00
|
|
|
intptr_t stack = (intptr_t)GetStackAddr(0);
|
|
|
|
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 IsSigAltStackFrame(int x) {
|
2022-05-18 23:41:29 +00:00
|
|
|
intptr_t stack = (intptr_t)GetStackAddr(0);
|
|
|
|
return (int)(stack >> 16) <= x &&
|
|
|
|
x <= (int)((stack + (SIGSTKSZ - FRAMESIZE)) >> 16);
|
2021-10-15 02:36:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
forceinline pureconst bool IsOldStackFrame(int x) {
|
|
|
|
intptr_t old = ROUNDDOWN(__oldstack, STACKSIZE);
|
|
|
|
return (old >> 16) <= x && x <= ((old + (STACKSIZE - FRAMESIZE)) >> 16);
|
|
|
|
}
|
|
|
|
|
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_ */
|