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"
|
2021-03-01 07:42:35 +00:00
|
|
|
#include "libc/macros.internal.h"
|
2021-01-17 03:18:37 +00:00
|
|
|
#include "libc/nt/enum/version.h"
|
2020-10-11 04:18:53 +00:00
|
|
|
#include "libc/runtime/runtime.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) \
|
2021-01-17 03:18:37 +00:00
|
|
|
(!(IsWindows() && NtGetVersion() < kNtVersionWindows10) ? NORMAL : WIN7)
|
2020-08-25 11:23:25 +00:00
|
|
|
|
2021-09-04 20:20:47 +00:00
|
|
|
struct MemoryInterval {
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
long h;
|
|
|
|
int prot;
|
|
|
|
int flags;
|
2022-03-20 15:01:14 +00:00
|
|
|
long offset;
|
|
|
|
long size;
|
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-04-24 16:59:22 +00:00
|
|
|
_Alignas(64) char 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;
|
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) {
|
|
|
|
return (int)(GetStaticStackAddr(0) >> 16) <= x &&
|
|
|
|
x <= (int)((GetStaticStackAddr(0) + (GetStackSize() - FRAMESIZE)) >>
|
|
|
|
16);
|
|
|
|
}
|
|
|
|
|
2021-10-15 02:36:49 +00:00
|
|
|
forceinline pureconst bool IsStaticStackFrame(int x) {
|
2022-03-16 20:33:13 +00:00
|
|
|
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);
|
2021-10-14 00:27:13 +00:00
|
|
|
}
|
|
|
|
|
2021-10-15 02:36:49 +00:00
|
|
|
forceinline pureconst bool IsSigAltStackFrame(int x) {
|
2022-03-16 20:33:13 +00:00
|
|
|
return (int)(GetStackAddr(0) >> 16) <= x &&
|
|
|
|
x <= (int)((GetStackAddr(0) + (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) {
|
|
|
|
m = (l + r) >> 1;
|
|
|
|
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_ */
|