//========================================================================= // Return the physical address of the PT corresponding to address lAddress //========================================================================= struct PT *GetPT(struct PML4 *pml4, long lAddress, unsigned short pid) { int pdIndex = GetPDIndex(lAddress); int pdpIndex = GetPDPIndex(lAddress); int pml4Index = GetPML4Index(lAddress); long pdp, pd, pt; pdp = VIRT(PML4,pml4) ->entries[pml4Index].value & 0xFFFFF000; if (!pdp) { long newpage = (long) AllocPage(pid); VIRT(PML4,pml4) ->entries[pml4Index].value = newpage | P | RW | US; pdp = newpage; } pd = VIRT(PDP,pdp) ->entries[pdpIndex].value & 0xFFFFF000; if (!pd) { long newpage = (long) AllocPage(pid); VIRT(PDP,pdp) ->entries[pdpIndex].value = newpage | P | RW | US; pd = newpage; } pt = VIRT(PD,pd) ->entries[pdIndex].value & 0xFFFFF000; if (!pt) { long newpage = (long) AllocPage(pid); VIRT(PD,pd) ->entries[pdIndex].value = newpage | P | RW | US; pt = newpage; } return (struct PT *) (pt & 0xFFFFF000); }
//========================================================= // Copy the given page and all consecutive subsequent ones //========================================================= void CopyPages(long address, struct Task *task) { address &= PageMask; // Get physical address of current PT struct PML4 *pml4 = (struct PML4 *) (task->cr3); struct PML4 *current_pml4 = (struct PML4 *) (currentTask->cr3); while (1) { struct PT *pt = GetPT(pml4, address, task->pid); struct PT *currentPT = GetPT(current_pml4, address, currentTask->pid); int i = GetPTIndex(address); if (!(VIRT(PT,currentPT) ->entries[i].value)) break; // Copy the physical memory p_Address data = AllocPage(task->pid); //data += VAddr / 8; CreatePTEWithPT((struct PML4 *)task->cr3, data, address, task->pid, US | RW | P | 0x800); memcpy( (void *) PAGE(((VIRT(PT, pt)) ->entries[i].value)) + VAddr, (void *) PAGE(((VIRT(PT, currentPT)) ->entries[i].value)) + VAddr, PageSize); address += PageSize; } }
//========================================================================= // Return the physical address of the PDP corresponding to address lAddress //========================================================================= struct PDP *GetPDP(struct PML4 *pml4, long lAddress, unsigned short pid) { int pml4Index = GetPML4Index(lAddress); long pdp = VIRT(PML4,pml4) ->entries[pml4Index].value & 0xFFFFF000; if (!pdp) { long newpage = (long) AllocPage(pid); VIRT(PML4,pml4) ->entries[pml4Index].value = newpage | P | RW | US; pdp = newpage; } return (struct PDP *) (pdp & 0xFFFFF000); }
//========================================================================= // Return the physical address of the PD corresponding to address lAddress //========================================================================= struct PD *GetPD(struct PML4 *pml4, long lAddress, unsigned short pid) { int pdpIndex = lAddress >> 30 & 0x1FF; int pml4Index = lAddress >> 39 & 0x1FF; long pdp, pd; pdp = VIRT(PML4,pml4) ->entries[pml4Index].value & 0xFFFFF000; if (!pdp) { long newpage = (long) AllocPage(pid); VIRT(PML4,pml4) ->entries[pml4Index].value = newpage | P | RW | US; pdp = newpage; } pd = VIRT(PDP,pdp) ->entries[pdpIndex].value & 0xFFFFF000; if (!pd) { long newpage = (long) AllocPage(pid); VIRT(PDP,pdp) ->entries[pdpIndex].value = newpage | P | RW | US; pd = newpage; } return (struct PD *) (pd & 0xFFFFF000); }
//===================================================== // Create a Page Table for a new process // Return a pointer to the Page Directory of this table //===================================================== void * VCreatePageDir(unsigned short pid, unsigned short parentPid) { struct PML4 *pml4; struct PD *pd; // Allocate the base page for the Page Table pml4 = (struct PML4 *) AllocPage(pid); VIRT(PML4,pml4) ->entries[GetPML4Index(VAddr)].value = virtualPDP | P | RW; // Physical to virtual addresses pd = GetPD(pml4, 0, pid); VIRT(PD,pd) ->entries[GetPDIndex(0)].value = kernelPT | P | RW; // Kernel entries if (parentPid == 0) // Just create some default PTEs // We need these two entries so that NewKernelTask can // access the data and stack pages of the new process. { long c; struct PT *pt = GetPT(pml4, UserData, pid); VIRT(PT,pt) ->entries[GetPTIndex(UserData)].value = AllocAndCreatePTE(TempUserData, pid, RW | P); c = TempUserData; asm ("invlpg %0;" : :"m"(*(char *)TempUserData) ); pt = GetPT(pml4, KernelStack, pid); VIRT(PT,pt) ->entries[GetPTIndex(KernelStack)].value = AllocAndCreatePTE(TempUStack, pid, RW | P); pt = GetPT(pml4, UserStack, pid); VIRT(PT,pt) ->entries[GetPTIndex(UserStack)].value = AllocAndCreatePTE(TempUStack, pid, RW | P); c = TempUStack; asm ("invlpg %0;" : :"m"(*(char *)TempUStack) ); }
int _cdecl main ( int argc, char *argv[] ) { ULONG UserAddress = 0; ULONG PageCount = 1 ; if ( argc > 1 ) { if ( strcmp ( argv[1], "/?" ) == 0 ) { Usage(); goto Exit; } if ( strcmp ( argv[1], "-?" ) == 0 ) { Usage(); goto Exit; } if ( sscanf ( argv[1], "%x", &UserAddress ) != 1 ) { Usage(); goto Exit; } } if ( argc > 2 ) { if ( sscanf ( argv[2], "%d", &PageCount ) != 1 ) { Usage(); goto Exit; } if ( PageCount == 0 ){ PageCount = 1; } } AllocPage( (PUCHAR)UserAddress, PageCount ); Exit : return 0; }
static void* reserve_code(struct jit* jit, lua_State* L, size_t sz) { struct page* page; size_t off = (jit->pagenum > 0) ? jit->pages[jit->pagenum-1]->off : 0; size_t size = (jit->pagenum > 0) ? jit->pages[jit->pagenum-1]->size : 0; if (off + sz >= size) { int i; uint8_t* pdata; cfunction func; /* need to create a new page */ jit->pages = (struct page**) realloc(jit->pages, (++jit->pagenum) * sizeof(jit->pages[0])); size = ALIGN_UP(sz + LINKTABLE_MAX_SIZE + sizeof(struct page), jit->align_page_size); page = (struct page*) AllocPage(size); jit->pages[jit->pagenum-1] = page; pdata = (uint8_t*) page; page->size = size; page->off = sizeof(struct page); lua_newtable(L); #define ADDFUNC(DLL, NAME) \ lua_pushliteral(L, #NAME); \ func = DLL ? (cfunction) GetProcAddressA(DLL, #NAME) : NULL; \ func = func ? func : (cfunction) &NAME; \ lua_pushcfunction(L, (lua_CFunction) func); \ lua_rawset(L, -3) ADDFUNC(NULL, check_double); ADDFUNC(NULL, check_float); ADDFUNC(NULL, check_uint64); ADDFUNC(NULL, check_int64); ADDFUNC(NULL, check_int32); ADDFUNC(NULL, check_uint32); ADDFUNC(NULL, check_uintptr); ADDFUNC(NULL, check_enum); ADDFUNC(NULL, check_typed_pointer); ADDFUNC(NULL, check_typed_cfunction); ADDFUNC(NULL, check_complex_double); ADDFUNC(NULL, check_complex_float); ADDFUNC(NULL, unpack_varargs_stack); ADDFUNC(NULL, unpack_varargs_stack_skip); ADDFUNC(NULL, unpack_varargs_reg); ADDFUNC(NULL, unpack_varargs_float); ADDFUNC(NULL, unpack_varargs_int); ADDFUNC(NULL, push_cdata); ADDFUNC(NULL, push_int); ADDFUNC(NULL, push_uint); ADDFUNC(NULL, lua_pushinteger); ADDFUNC(NULL, push_float); ADDFUNC(jit->kernel32_dll, SetLastError); ADDFUNC(jit->kernel32_dll, GetLastError); ADDFUNC(jit->lua_dll, luaL_error); ADDFUNC(jit->lua_dll, lua_pushnumber); ADDFUNC(jit->lua_dll, lua_pushboolean); ADDFUNC(jit->lua_dll, lua_gettop); ADDFUNC(jit->lua_dll, lua_rawgeti); ADDFUNC(jit->lua_dll, lua_pushnil); ADDFUNC(jit->lua_dll, lua_callk); ADDFUNC(jit->lua_dll, lua_settop); ADDFUNC(jit->lua_dll, lua_remove); //CHANGES: BEGIN ADDFUNC(jit->lua_dll, lua_pushlightuserdata); //CHANGES: END #undef ADDFUNC for (i = 0; extnames[i] != NULL; i++) { if (strcmp(extnames[i], "FUNCTION") == 0) { shred(pdata + page->off, 0, JUMP_SIZE); jit->function_extern = i; } else { lua_getfield(L, -1, extnames[i]); func = (cfunction) lua_tocfunction(L, -1); if (func == NULL) { luaL_error(L, "internal error: missing link for %s", extnames[i]); } compile_extern_jump(jit, L, func, pdata + page->off); lua_pop(L, 1); } page->off += JUMP_SIZE; } page->freed = page->off; lua_pop(L, 1); } else { page = jit->pages[jit->pagenum-1]; EnableWrite(page, page->size); } return (uint8_t*) page + page->off; }
void *malloc(size_t size) { heap_t *Heap, *tmp_Heap; void *Address; if(size == 0) return NULL; if(Heap_Entries == 0) //Es wurde bisher kein Speicher angefordert { uint64_t Pages = (size + sizeof(heap_t)) / 4096 + 1; //if((size + sizeof(heap_t)) % 4096 != 0) Pages++; Heap_Base = AllocPage(Pages); //Pages reservieren if(Heap_Base == NULL) return NULL; Heap = (heap_t*)Heap_Base; Heap->Next = NULL; Heap->Prev = NULL; Heap->Length = size; //Grösse des Heaps entspricht dem angeforderten Speicherplatz //Heap->Length = Pages * 4096 - sizeof(heap_t); //Speicher für den Header abziehen //Jetzt angefordeten Speicher reservieren Address = (void*)((uintptr_t)Heap + sizeof(heap_t)); Heap->Flags = HEAP_FLAGS | HEAP_RESERVED; //Reserved-Bit setzen if((Heap->Length + 2 * sizeof(heap_t)) <= (Pages * 4096)) { tmp_Heap = Address + size; setupNewHeapEntry(Heap, tmp_Heap); tmp_Heap->Length = Pages * 4096 - size - 2 * sizeof(heap_t); //tmp_Heap->Length = Heap->Length - size - sizeof(heap_t);//Heapheader abziehen //Heap->Length = size; //Länge des ersten Speicherbereichs aktualisieren Heap_Entries = 2; } else //Hat nur ein Header Platz, gebe den Speicher dem vorhergehenden Header { Heap_Entries = 1; } } else //Es wurde schon Speicher reserviert { Heap = Heap_Base; uint64_t i; //Die Header durchsuchen und schauen, ob dort freier Speicher verfügbar ist for(i = 0; i < Heap_Entries; i++) { if((Heap->Flags & HEAP_RESERVED) || (Heap->Length < size)) { if(Heap->Next == NULL) break; //Es sind keine weiteren Headers vorhanden Heap = Heap->Next; continue; //Wenn dieser Speicherbereich reserviert oder zu klein ist, zum nächsten gehen } if (Heap->Length >= size + sizeof(heap_t)) //Speicherbereich zu gross und Platz für einen Header => Speicherbereich anpassen { Address = (void*)((uintptr_t)Heap + sizeof(heap_t)); tmp_Heap = Address + size; setupNewHeapEntry(Heap, tmp_Heap); tmp_Heap->Length = Heap->Length - size - sizeof(heap_t); Heap->Length = size; //Länge anpassen Heap->Flags |= HEAP_RESERVED; //Als reserviert markieren return Address; } else //Wenn kein neuer Header platz hat, dann ist der Speicherbereich halt zu gross { Heap->Flags |= HEAP_RESERVED; //Als reserviert markieren return (void*)((uintptr_t)Heap + sizeof(heap_t)); } } //Wenn kein passender Heapeintrag gefunden wurde, dann muss neuer Speicher angefordert werden /*if (Heap->Flags & HEAP_RESERVED) {*/ tmp_Heap = Heap; uint64_t Pages = (size + sizeof(heap_t)) / 4096 + 1; //if((size + sizeof(heap_t)) % 4096 != 0) Pages++; Heap = AllocPage(Pages); //Eine Page reservieren if(Heap == NULL) return NULL; Heap_Entries++; tmp_Heap->Next = Heap; Heap->Next = NULL; Heap->Prev = tmp_Heap; Heap->Length = size; //Heap->Length = Pages * 4096 - sizeof(heap_t); //Speicher für den Header abziehen Address = (void*)((uintptr_t)Heap + sizeof(heap_t)); Heap->Flags = HEAP_FLAGS | HEAP_RESERVED; //Reserved-Bit setzen if (Heap->Length <= Pages * 4096 - 2 * sizeof(heap_t)) { tmp_Heap = Address + size; setupNewHeapEntry(Heap, tmp_Heap); tmp_Heap->Length = Pages * 4096 - size - 2 * sizeof(heap_t); } /*} else //Der aktuelle Speicherbereich ist zu klein TODO: Funktioniert nicht wegen Fragmentierung { size_t additionalSize = size - Heap->Length; uint64_t Pages = additionalSize / 4096 + 1; if(AllocPage(Pages) == NULL) return NULL; //Eine Page reservieren Heap->Length += Pages * 4096; Address = (void*)((uintptr_t)Heap + sizeof(heap_t)); Heap->Flags = HEAP_FLAGS | HEAP_RESERVED; //Reserved-Bit setzen if (additionalSize <= Pages * 4096 - sizeof(heap_t)) { tmp_Heap = Address + size; setupNewHeapEntry(Heap, tmp_Heap); } }*/ //Neuer Speicher anfordern /*Heap = Heap_Base; register uint64_t i; for(i = 0; i < Heap_Entries; i++) Heap = Heap->Next; size_t AllocSize = size - Heap->Length; uint64_t Pages = (size % 4096 != 0) ? size / 4096 + 1 : size / 4096; tmp_Heap = AllocPage(Pages);*/ } return Address; }
System::UIntPtr^ PREFIXED(AllocManager)::Alloc() { return gcnew System::UIntPtr(AllocPage()); }