mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-05 10:48:29 +00:00
Rewrite memory manager
Actually Portable Executable now supports Android. Cosmo's old mmap code required a 47 bit address space. The new implementation is very agnostic and supports both smaller address spaces (e.g. embedded) and even modern 56-bit PML5T paging for x86 which finally came true on Zen4 Threadripper Cosmopolitan no longer requires UNIX systems to observe the Windows 64kb granularity; i.e. sysconf(_SC_PAGE_SIZE) will now report the host native page size. This fixes a longstanding POSIX conformance issue, concerning file mappings that overlap the end of file. Other aspects of conformance have been improved too, such as the subtleties of address assignment and and the various subtleties surrounding MAP_FIXED and MAP_FIXED_NOREPLACE On Windows, mappings larger than 100 megabytes won't be broken down into thousands of independent 64kb mappings. Support for MAP_STACK is removed by this change; please use NewCosmoStack() instead. Stack overflow avoidance is now being implemented using the POSIX thread APIs. Please use GetStackBottom() and GetStackAddr(), instead of the old error-prone GetStackAddr() and HaveStackMemory() APIs which are removed.
This commit is contained in:
parent
7f6d0b8709
commit
6ffed14b9c
150 changed files with 1893 additions and 5634 deletions
|
@ -1,189 +1,22 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
|
||||
#include "ape/sections.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/sysv/consts/ss.h"
|
||||
#include "libc/thread/tls.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define kAutomapStart 0x100080040000
|
||||
#define kAutomapSize (kMemtrackStart - kAutomapStart)
|
||||
#define kMemtrackStart 0x1fe7fffc0000
|
||||
#define kMemtrackSize (0x1ffffffc0000 - kMemtrackStart)
|
||||
#ifndef __SANITIZE_ADDRESS__
|
||||
#define kFixedmapStart 0x300000000
|
||||
#define kFixedmapSize (0x400000000 - kFixedmapStart)
|
||||
#define kMemtrackFdsStart 0x6fe000000
|
||||
#define kMemtrackFdsSize (0x6ff000000 - kMemtrackFdsStart)
|
||||
#define kMemtrackZiposStart 0x6fd000000
|
||||
#define kMemtrackZiposSize (0xafe000000 - kMemtrackZiposStart)
|
||||
#else
|
||||
#define kFixedmapStart 0x300000040000
|
||||
#define kFixedmapSize (0x400000040000 - kFixedmapStart)
|
||||
#define kMemtrackNsyncStart 0x6fc000040000
|
||||
#define kMemtrackNsyncSize (0x6fcffffc0000 - kMemtrackNsyncStart)
|
||||
#define kMemtrackFdsStart 0x6fe000040000
|
||||
#define kMemtrackFdsSize (0x6feffffc0000 - kMemtrackFdsStart)
|
||||
#define kMemtrackZiposStart 0x6fd000040000
|
||||
#define kMemtrackZiposSize (0x6fdffffc0000 - kMemtrackZiposStart)
|
||||
#define kMemtrackGran (!IsAsan() ? FRAMESIZE : FRAMESIZE * 8)
|
||||
|
||||
struct MemoryInterval {
|
||||
int x;
|
||||
int y;
|
||||
long h;
|
||||
long size;
|
||||
long offset;
|
||||
int flags;
|
||||
char prot;
|
||||
bool iscow;
|
||||
bool readonlyfile;
|
||||
};
|
||||
|
||||
struct MemoryIntervals {
|
||||
size_t i, n;
|
||||
struct MemoryInterval *p;
|
||||
struct MemoryInterval s[16];
|
||||
};
|
||||
|
||||
extern struct MemoryIntervals _mmi;
|
||||
|
||||
void __mmi_lock(void);
|
||||
void __mmi_unlock(void);
|
||||
bool IsMemtracked(int, int);
|
||||
void PrintSystemMappings(int);
|
||||
unsigned __find_memory(const struct MemoryIntervals *, int) nosideeffect;
|
||||
bool __check_memtrack(const struct MemoryIntervals *) nosideeffect;
|
||||
void PrintMemoryIntervals(int, const struct MemoryIntervals *);
|
||||
int __track_memory(struct MemoryIntervals *, int, int, long, int, int, bool,
|
||||
bool, long, long);
|
||||
int __untrack_memory(struct MemoryIntervals *, int, int,
|
||||
void (*)(struct MemoryIntervals *, int, int));
|
||||
void __release_memory_nt(struct MemoryIntervals *, int, int);
|
||||
int __untrack_memories(void *, size_t);
|
||||
size_t __get_memtrack_size(struct MemoryIntervals *) nosideeffect;
|
||||
|
||||
#ifdef __x86_64__
|
||||
/*
|
||||
* AMD64 has 48-bit signed pointers (PML4T)
|
||||
* AMD64 is trying to go bigger, i.e. 57-bit (PML5T)
|
||||
* LINUX forbids userspace from leveraging negative pointers
|
||||
* Q-EMU may impose smaller vaspaces emulating AMD on non-AMD
|
||||
*
|
||||
* Having "signed pointers" means these top sixteen bits
|
||||
*
|
||||
* 0x0000000000000000
|
||||
* ^^^^
|
||||
*
|
||||
* must be
|
||||
*
|
||||
* - 0000 for positive pointers
|
||||
* - FFFF for negative pointers
|
||||
*
|
||||
* otherwise the instruction using the faulty pointer will fault.
|
||||
*/
|
||||
#define IsLegalPointer(p) \
|
||||
(-0x800000000000 <= (intptr_t)(p) && (intptr_t)(p) <= 0x7fffffffffff)
|
||||
#define ADDR_32_TO_48(x) (intptr_t)((uint64_t)(int)(x) << 16)
|
||||
#elif defined(__aarch64__)
|
||||
/*
|
||||
* ARM64 has 48-bit unsigned pointers (Armv8.0-A)
|
||||
* ARM64 can possibly go bigger, i.e. 52-bit (Armv8.2-A)
|
||||
* ARM64 can impose arbitrarily smaller vaspaces, e.g. 40/44-bit
|
||||
* APPLE in their limitless authoritarianism forbids 32-bit pointers
|
||||
*/
|
||||
#define IsLegalPointer(p) ((uintptr_t)(p) <= 0xffffffffffff)
|
||||
#define ADDR_32_TO_48(x) (uintptr_t)((uint64_t)(uint32_t)(x) << 16)
|
||||
#else
|
||||
/* RISC-V Sipeed Nezha has 39-bit vaspace */
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
|
||||
forceinline pureconst bool IsLegalSize(uint64_t n) {
|
||||
/* subtract frame size so roundup is safe */
|
||||
return n <= 0x800000000000 - FRAMESIZE;
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsAutoFrame(int x) {
|
||||
return (int)(kAutomapStart >> 16) <= x &&
|
||||
x <= (int)((kAutomapStart + kAutomapSize - 1) >> 16);
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsMemtrackFrame(int x) {
|
||||
return (int)(kAutomapStart >> 16) <= x &&
|
||||
x <= (int)((kAutomapStart + kAutomapSize - 1) >> 16);
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsGfdsFrame(int x) {
|
||||
return (int)(kMemtrackFdsStart >> 16) <= x &&
|
||||
x <= (int)((kMemtrackFdsStart + kMemtrackFdsSize - 1) >> 16);
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsNsyncFrame(int x) {
|
||||
return (int)(kMemtrackNsyncStart >> 16) <= x &&
|
||||
x <= (int)((kMemtrackNsyncStart + kMemtrackNsyncSize - 1) >> 16);
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsZiposFrame(int x) {
|
||||
return (int)(kMemtrackZiposStart >> 16) <= x &&
|
||||
x <= (int)((kMemtrackZiposStart + kMemtrackZiposSize - 1) >> 16);
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsShadowFrame(int x) {
|
||||
return 0x7fff <= x && x < 0x10008000;
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsStaticStackFrame(int x) {
|
||||
intptr_t stack = GetStaticStackAddr(0);
|
||||
return (int)(stack >> 16) <= x &&
|
||||
x <= (int)((stack + (GetStackSize() - FRAMESIZE)) >> 16);
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsStackFrame(int x) {
|
||||
intptr_t stack = GetStackAddr();
|
||||
return (int)(stack >> 16) <= x &&
|
||||
x <= (int)((stack + (GetStackSize() - FRAMESIZE)) >> 16);
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsOldStack(const void *x) {
|
||||
size_t foss_stack_size = 8ul * 1024 * 1024;
|
||||
uintptr_t top = __oldstack + foss_stack_size;
|
||||
uintptr_t bot = __oldstack - foss_stack_size;
|
||||
return bot <= (uintptr_t)x && (uintptr_t)x < top;
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsOldStackFrame(int x) {
|
||||
size_t foss_stack_size = 8ul * 1024 * 1024;
|
||||
uintptr_t top = __oldstack + foss_stack_size;
|
||||
uintptr_t bot = __oldstack - foss_stack_size;
|
||||
return (int)(bot >> 16) <= x && x <= (int)((top >> 16) - 1);
|
||||
}
|
||||
|
||||
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 *BegA, *EndA, *BegB, *EndB;
|
||||
if (n) {
|
||||
BegA = p;
|
||||
EndA = BegA + n;
|
||||
BegB = __executable_start;
|
||||
EndB = _end;
|
||||
return MAX(BegA, BegB) < MIN(EndA, EndB);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
forceinline pureconst bool OverlapsShadowSpace(const void *p, size_t n) {
|
||||
intptr_t BegA, EndA, BegB, EndB;
|
||||
if (n) {
|
||||
BegA = (intptr_t)p;
|
||||
EndA = BegA + n;
|
||||
BegB = 0x7fff0000;
|
||||
EndB = 0x100080000000;
|
||||
return MAX(BegA, BegB) < MIN(EndA, EndB);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue