mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-29 13:48:21 +00:00
fix several issues relating to elf and registers and add mmap
This commit is contained in:
+45
-2
@@ -106,6 +106,17 @@ static char* debugnames[] = {
|
||||
"FILE"
|
||||
};
|
||||
|
||||
static void debug_dumpusermappings(){
|
||||
vmm_mapping* map = arch_getcls()->context->userstart;
|
||||
|
||||
printf("User mappings:\n");
|
||||
|
||||
while(map != NULL){
|
||||
printf("START: %016p END: %016p MMUFLAGS: %016p DATA: %016p OFFSET: %lu TYPE: %s\n", map->start, map->end, map->mmuflags, map->data, map->offset, debugnames[map->type]);
|
||||
map = map->next;
|
||||
}
|
||||
|
||||
}
|
||||
static void debug_dumpkernelmappings(){
|
||||
vmm_mapping* map = kmapstart;
|
||||
|
||||
@@ -375,6 +386,31 @@ void* vmm_alloc(size_t pagec, size_t mmuflags){
|
||||
return addr;
|
||||
}
|
||||
|
||||
void* vmm_allocfrom(void* addr, size_t mmuflags, size_t pagec){
|
||||
|
||||
int* lock;
|
||||
vmm_mapping** start;
|
||||
|
||||
getcontextinfo(addr, &lock, &start);
|
||||
|
||||
spinlock_acquire(lock);
|
||||
|
||||
addr = findfirstfreearea(findmappingfromaddr(*start, addr), pagec);
|
||||
|
||||
if(!addr)
|
||||
goto _done;
|
||||
|
||||
if(!setmap(start, addr, pagec, mmuflags, VMM_TYPE_ANON, 0, 0))
|
||||
addr = NULL;
|
||||
|
||||
_done:
|
||||
|
||||
spinlock_release(lock);
|
||||
|
||||
return addr;
|
||||
|
||||
}
|
||||
|
||||
bool vmm_unmap(void* addr, size_t pagec){
|
||||
|
||||
int* lock;
|
||||
@@ -448,6 +484,14 @@ bool vmm_allocnowat(void* addr, size_t mmuflags, size_t size){
|
||||
|
||||
spinlock_acquire(lock);
|
||||
|
||||
vmm_mapping* m = findmappingfromaddr(*start, addr);
|
||||
|
||||
if(m->type != VMM_TYPE_FREE || (addr + size*PAGE_SIZE-1) > m->end){
|
||||
spinlock_release(lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// XXX allocate 1 page at a time to reduce fragmentation
|
||||
|
||||
void* paddr = pmm_alloc(size);
|
||||
@@ -480,7 +524,6 @@ bool vmm_dealwithrequest(void* addr){
|
||||
if(!start) return false;
|
||||
|
||||
spinlock_acquire(lock);
|
||||
|
||||
|
||||
bool status;
|
||||
vmm_mapping* map = findmappingfromaddr(*start, addr);
|
||||
@@ -498,7 +541,7 @@ bool vmm_dealwithrequest(void* addr){
|
||||
|
||||
addr = (size_t)addr & ~(0xFFF);
|
||||
|
||||
printf("Demand paging %p\n", addr);
|
||||
//printf("Demand paging %p\n", addr);
|
||||
|
||||
|
||||
|
||||
|
||||
+66
-11
@@ -57,7 +57,7 @@ static void* stacksetup(char* interp, char** argv, char** env, elf_header64 head
|
||||
size_t initialsize = 0;
|
||||
size_t argdatasize = 0;
|
||||
size_t envdatasize = 0;
|
||||
size_t auxvsize = 5*8; // FIXME better way of keeping track of this
|
||||
size_t auxvsize = 5*16; // FIXME better way of keeping track of this
|
||||
|
||||
while(argv[argc]){
|
||||
argdatasize += strlen(argv[argc]) + 1;
|
||||
@@ -90,8 +90,7 @@ static void* stacksetup(char* interp, char** argv, char** env, elf_header64 head
|
||||
|
||||
// get the addresses to copy the data to
|
||||
|
||||
elf_ph64* phdrdatastart = STACK_TOP - header.ph_count * header.ph_size;
|
||||
char* argdatastart = (void*) phdrdatastart - argdatasize;
|
||||
char* argdatastart = STACK_TOP - argdatasize;
|
||||
char* envdatastart = argdatastart - envdatasize;
|
||||
|
||||
auxv64_t* auxvstart = (void*)(((uintptr_t)envdatastart & (~0xF)) - auxvsize);
|
||||
@@ -108,10 +107,8 @@ static void* stacksetup(char* interp, char** argv, char** env, elf_header64 head
|
||||
// AT_PHDR
|
||||
|
||||
auxvstart->a_type = AT_PHDR;
|
||||
auxvstart->a_val = (uint64_t)phdrdatastart;
|
||||
auxvstart->a_val = (uint64_t)phs;
|
||||
auxvstart++;
|
||||
|
||||
memcpy(phdrdatastart, phs, header.ph_count * header.ph_size);
|
||||
|
||||
// AT_PHENT
|
||||
|
||||
@@ -123,6 +120,7 @@ static void* stacksetup(char* interp, char** argv, char** env, elf_header64 head
|
||||
|
||||
auxvstart->a_type = AT_PHNUM;
|
||||
auxvstart->a_val = header.ph_count;
|
||||
auxvstart++;
|
||||
|
||||
// AT_ENTRY
|
||||
|
||||
@@ -133,6 +131,7 @@ static void* stacksetup(char* interp, char** argv, char** env, elf_header64 head
|
||||
// AT_NULL
|
||||
|
||||
auxvstart->a_type = AT_NULL;
|
||||
auxvstart->a_val = 0;
|
||||
|
||||
// copy the data
|
||||
|
||||
@@ -174,6 +173,7 @@ int elf_load(thread_t* thread, vnode_t* node, char** argv, char** env){
|
||||
|
||||
elf_header64 header;
|
||||
elf_header64 progheader;
|
||||
vnode_t* prognode = node;
|
||||
elf_ph64 ph;
|
||||
|
||||
int err = 0;
|
||||
@@ -193,7 +193,7 @@ int elf_load(thread_t* thread, vnode_t* node, char** argv, char** env){
|
||||
// and also save the executable's program headers
|
||||
// for auxv
|
||||
|
||||
elf_ph64 progphs[header.ph_count];
|
||||
elf_ph64* progphs;
|
||||
|
||||
for(size_t currentph = 0; currentph < header.ph_count; ++currentph){
|
||||
readc = vfs_read(&err, node, &ph, header.ph_size, header.ph_pos + currentph*header.ph_size);
|
||||
@@ -202,15 +202,16 @@ int elf_load(thread_t* thread, vnode_t* node, char** argv, char** env){
|
||||
if(readc != header.ph_size)
|
||||
return EINVAL;
|
||||
|
||||
memcpy(progphs+currentph, &ph, sizeof(elf_ph64));
|
||||
|
||||
if(ph.type == PH_TYPE_PHDR)
|
||||
progphs = (elf_ph64*)ph.memaddr;
|
||||
|
||||
if(ph.type == PH_TYPE_INTERPRETER){
|
||||
|
||||
// load the name and elf header of the interpreter
|
||||
|
||||
progheader = header;
|
||||
|
||||
char* interp = alloc(ph.fsize + 1);
|
||||
interp = alloc(ph.fsize + 1);
|
||||
if(!interp)
|
||||
return ENOMEM;
|
||||
|
||||
@@ -300,12 +301,66 @@ int elf_load(thread_t* thread, vnode_t* node, char** argv, char** env){
|
||||
|
||||
}
|
||||
|
||||
// also load the executable memory image if we're using an interpreter
|
||||
|
||||
if(interp){
|
||||
for(size_t currentph = 0; currentph < header.ph_count; ++currentph){
|
||||
|
||||
// read ph
|
||||
|
||||
readc = vfs_read(&err, prognode, &ph, progheader.ph_size, progheader.ph_pos + currentph*progheader.ph_size);
|
||||
|
||||
if(err) goto _fail;
|
||||
|
||||
if(readc != progheader.ph_size){
|
||||
err = EINVAL;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
if(ph.type != PH_TYPE_LOAD)
|
||||
continue;
|
||||
|
||||
if(!vmm_allocnowat((void*)ph.memaddr, phflagtommuflag(ph.flags), ph.msize)){
|
||||
err = ENOMEM;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
// set up temporary mmu flags to copy data
|
||||
|
||||
arch_mmu_changeflags(arch_getcls()->context->context, ph.memaddr, ARCH_MMU_MAP_READ | ARCH_MMU_MAP_WRITE, ph.msize / PAGE_SIZE + (ph.msize % PAGE_SIZE ? 1 : 0));
|
||||
|
||||
// read program data
|
||||
|
||||
readc = vfs_read(&err, prognode, (void*)ph.memaddr, ph.fsize, ph.offset);
|
||||
|
||||
if(err)
|
||||
goto _fail;
|
||||
|
||||
if(readc != ph.fsize){
|
||||
err = EINVAL;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
// zero if needed
|
||||
|
||||
size_t zerocount = ph.msize - ph.fsize;
|
||||
|
||||
if(zerocount){
|
||||
void* zeroaddr = ph.memaddr + ph.fsize;
|
||||
memset(zeroaddr, 0, zerocount);
|
||||
}
|
||||
|
||||
// reset proper mmu flags
|
||||
|
||||
arch_mmu_changeflags(arch_getcls()->context->context, ph.memaddr, phflagtommuflag(ph.flags), ph.msize / PAGE_SIZE + (ph.msize % PAGE_SIZE ? 1 : 0));
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void* stack = stacksetup(interp, argv, env, progheader, progphs);
|
||||
|
||||
|
||||
arch_regs_setupuser(thread->regs, (void*)header.entry, stack, true);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -17,7 +17,7 @@ syscallret syscall_libc_log(char* str){
|
||||
|
||||
strcpy(buf, str);
|
||||
|
||||
printf("%s", str);
|
||||
printf("%s\n", str);
|
||||
|
||||
ret.errno = 0;
|
||||
ret.ret = 0;
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
#include <kernel/syscalls.h>
|
||||
#include <kernel/vmm.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
// linux abi
|
||||
|
||||
#define PROT_NONE 0x00
|
||||
#define PROT_READ 0x01
|
||||
#define PROT_WRITE 0x02
|
||||
#define PROT_EXEC 0x04
|
||||
|
||||
#define MAP_FILE 0x00
|
||||
#define MAP_SHARED 0x01
|
||||
#define MAP_PRIVATE 0x02
|
||||
#define MAP_FIXED 0x10
|
||||
#define MAP_ANON 0x20
|
||||
#define MAP_ANONYMOUS 0x20
|
||||
#define MAP_NORESERVE 0x4000
|
||||
|
||||
#define MS_ASYNC 0x01
|
||||
#define MS_INVALIDATE 0x02
|
||||
#define MS_SYNC 0x04
|
||||
|
||||
#define MCL_CURRENT 0x01
|
||||
#define MCL_FUTURE 0x02
|
||||
|
||||
#define POSIX_MADV_NORMAL 0
|
||||
#define POSIX_MADV_RANDOM 1
|
||||
#define POSIX_MADV_SEQUENTIAL 2
|
||||
#define POSIX_MADV_WILLNEED 3
|
||||
#define POSIX_MADV_DONTNEED 4
|
||||
|
||||
#define MADV_NORMAL 0
|
||||
#define MADV_RANDOM 1
|
||||
#define MADV_SEQUENTIAL 2
|
||||
#define MADV_WILLNEED 3
|
||||
#define MADV_DONTNEED 4
|
||||
#define MADV_FREE 8
|
||||
|
||||
#define MREMAP_MAYMOVE 1
|
||||
#define MREMAP_FIXED 2
|
||||
|
||||
#define MFD_CLOEXEC 1U
|
||||
#define MFD_ALLOW_SEALING 2U
|
||||
|
||||
syscallret syscall_mmap(void* hint, size_t len, int prot, int flags, int fd, off_t offset){
|
||||
syscallret retv;
|
||||
|
||||
retv.ret = -1;
|
||||
retv.errno = 0;
|
||||
|
||||
if(len == 0 || hint > USER_SPACE_END){
|
||||
retv.errno = EINVAL;
|
||||
return retv;
|
||||
}
|
||||
|
||||
if(flags != (MAP_ANON | MAP_PRIVATE)){
|
||||
retv.errno = ENOSYS;
|
||||
return retv;
|
||||
|
||||
}
|
||||
|
||||
size_t mmuflags = 0;
|
||||
|
||||
if(prot & PROT_READ)
|
||||
mmuflags |= ARCH_MMU_MAP_READ;
|
||||
|
||||
if(prot & PROT_WRITE)
|
||||
mmuflags |= ARCH_MMU_MAP_WRITE;
|
||||
|
||||
if(!prot & PROT_EXEC)
|
||||
mmuflags |= ARCH_MMU_MAP_NOEXEC;
|
||||
|
||||
mmuflags |= ARCH_MMU_MAP_USER;
|
||||
|
||||
size_t plen = len / PAGE_SIZE + (len % PAGE_SIZE ? 1 : 0);
|
||||
|
||||
void* ret = NULL;
|
||||
|
||||
if(hint)
|
||||
ret = vmm_allocnowat(hint, mmuflags, plen) ? hint : NULL; // TODO demand page
|
||||
|
||||
if(!ret && !(flags & MAP_FIXED))
|
||||
ret = vmm_allocfrom(USER_ALLOC_START, mmuflags, len);
|
||||
|
||||
if(!ret){
|
||||
retv.errno = ENOMEM;
|
||||
if(flags & MAP_ANON)
|
||||
memset(ret, 0, plen);
|
||||
}
|
||||
else
|
||||
retv.ret = ret;
|
||||
|
||||
return retv;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user