89 lines
2.5 KiB
C
89 lines
2.5 KiB
C
#include "emulibc.h"
|
|
#include <stdio.h>
|
|
#include <sys/mman.h>
|
|
|
|
// Keep this in sync with the rust code!!
|
|
struct __AddressRange {
|
|
unsigned long start;
|
|
unsigned long size;
|
|
};
|
|
struct __WbxSysLayout {
|
|
struct __AddressRange elf;
|
|
struct __AddressRange main_thread;
|
|
struct __AddressRange alt_thread;
|
|
struct __AddressRange sbrk;
|
|
struct __AddressRange sealed;
|
|
struct __AddressRange invis;
|
|
struct __AddressRange plain;
|
|
struct __AddressRange mmap;
|
|
};
|
|
ECL_INVISIBLE ECL_EXPORT struct __WbxSysLayout __wbxsysinfo;
|
|
|
|
void* alloc_helper(size_t size, const struct __AddressRange* range, unsigned long* current, const char* name)
|
|
{
|
|
if (!*current)
|
|
{
|
|
printf("Initializing heap %s at %p:%p\n", name, (void*)range->start, (void*)(range->start + range->size));
|
|
*current = range->start;
|
|
}
|
|
|
|
unsigned long start = *current;
|
|
unsigned long end = start + size;
|
|
end = (end + 15) & ~15ul;
|
|
|
|
if (end < start || end > range->start + range->size)
|
|
{
|
|
fprintf(stderr, "Failed to satisfy allocation of %lu bytes on %s heap\n", size, name);
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
unsigned long pstart = (start + 0xfff) & ~0xffful;
|
|
unsigned long pend = (end + 0xfff) & ~0xffful;
|
|
if (pstart < pend)
|
|
{
|
|
if (mmap((void*)pstart, pend - pstart, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_FIXED_NOREPLACE, -1, 0) == MAP_FAILED)
|
|
{
|
|
fprintf(stderr, "VERY STRANGE: mmap() failed to satisfy allocation of %lu bytes on %s heap\n", size, name);
|
|
return NULL;
|
|
}
|
|
}
|
|
printf("Allocated %lu bytes on %s heap, usage %lu/%lu\n", size, name, end - range->start, range->size);
|
|
*current = end;
|
|
return (void*)start;
|
|
}
|
|
}
|
|
|
|
static unsigned long __sealed_current;
|
|
void* alloc_sealed(size_t size)
|
|
{
|
|
return alloc_helper(size, &__wbxsysinfo.sealed, &__sealed_current, "sealed");
|
|
}
|
|
|
|
static unsigned long __invisible_current;
|
|
void* alloc_invisible(size_t size)
|
|
{
|
|
return alloc_helper(size, &__wbxsysinfo.invis, &__invisible_current, "invisible");
|
|
}
|
|
|
|
static unsigned long __plain_current;
|
|
void* alloc_plain(size_t size)
|
|
{
|
|
return alloc_helper(size, &__wbxsysinfo.plain, &__plain_current, "plain");
|
|
}
|
|
|
|
// TODO: This existed before we even had stdio support. Retire?
|
|
void _debug_puts(const char *s)
|
|
{
|
|
fprintf(stderr, "%s\n", s);
|
|
}
|
|
|
|
ECL_EXPORT void ecl_seal()
|
|
{
|
|
if (__sealed_current)
|
|
{
|
|
if (mprotect((void*)__wbxsysinfo.sealed.start, (__sealed_current - __wbxsysinfo.sealed.start + 0xfff) & ~0xffful, PROT_READ) != 0)
|
|
__asm__("int3");
|
|
}
|
|
}
|