Area* AddressSpace::CreateArea(const char name[], unsigned int size, AreaWiring wiring, PageProtection protection, PageCache *cache, off_t offset, unsigned int va, int flags) { if (size % PAGE_SIZE != 0 || size == 0) return 0; if (cache != 0 && cache->Commit(offset + size) != offset + size) return 0; fAreaLock.LockWrite(); if (va == INVALID_PAGE) va = FindFreeRange(size, flags); else if (va % PAGE_SIZE != 0 || !fAreas.IsRangeFree(va, va + size - 1)) va = INVALID_PAGE; Area *area = 0; if (va != INVALID_PAGE) { area = new Area(name, protection, cache, offset, wiring); fAreas.Add(area, va, va + size - 1); if (wiring & AREA_WIRED) { for (unsigned int aroffs = 0; aroffs < size; aroffs += PAGE_SIZE) { Page *page = area->GetPageCache()->GetPage(area->GetCacheOffset() + aroffs, false); page->Wire(); fPhysicalMap->Map(va + aroffs, page->GetPhysicalAddress(), protection); } } } fChangeCount++; fAreaLock.UnlockWrite(); return area; }
Area* AddressSpace::MapPhysicalMemory(const char name[], unsigned int pa, unsigned int size, PageProtection protection) { fAreaLock.LockWrite(); unsigned int va = FindFreeRange(size); if (va == INVALID_PAGE) { fAreaLock.UnlockWrite(); return 0; } Area *area = new Area(name, protection, 0, 0, AREA_WIRED); fAreas.Add(area, va, va + size - 1); for (unsigned int aroffs = 0; aroffs < size; aroffs += PAGE_SIZE) fPhysicalMap->Map(va + aroffs, pa + aroffs, protection); fChangeCount++; fAreaLock.UnlockWrite(); return area; }
void *Elf32Load(int FD, Elf32_Ehdr *hdr) { ENTER("iFD", FD); // Check for a program header if(hdr->e_phoff == 0) { #if DEBUG_WARN Warning("ELF File does not contain a program header\n"); #endif LEAVE('n'); return NULL; } // Read Program Header Table Elf32_Phdr* phtab = malloc( sizeof(Elf32_Phdr) * hdr->e_phnum ); if( !phtab ) { LEAVE('n'); return NULL; } LOG("hdr.e_phoff = 0x%08x\n", hdr->e_phoff); acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET); acess__SysRead(FD, phtab, sizeof(Elf32_Phdr) * hdr->e_phnum); // Count Pages unsigned int iPageCount = 0; LOG("hdr.e_phnum = %i\n", hdr->e_phnum); for( unsigned int i = 0; i < hdr->e_phnum; i++ ) { // Ignore Non-LOAD types if(phtab[i].p_type != PT_LOAD) continue; iPageCount += ((phtab[i].p_vaddr&0xFFF) + phtab[i].p_memsz + 0xFFF) >> 12; LOG("phtab[%i] = {p_vaddr:0x%x, p_memsz:0x%x}\n", i, phtab[i].p_vaddr, phtab[i].MemSize); } LOG("iPageCount = %i\n", iPageCount); // Allocate Information Structure //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount ); // Fill Info Struct //ret->Entry = hdr.entrypoint; //ret->Base = -1; // Set Base to maximum value //ret->NumPages = iPageCount; //ret->Interpreter = NULL; // Prescan for base and size uint32_t max = 0; uint32_t base = UINT32_MAX; for( unsigned int i = 0; i < hdr->e_phnum; i ++) { if( phtab[i].p_type != PT_LOAD ) continue; if( phtab[i].p_vaddr < base ) base = phtab[i].p_vaddr; if( phtab[i].p_vaddr + phtab[i].p_memsz > max ) max = phtab[i].p_vaddr + phtab[i].p_memsz; } LOG("base = %08x, max = %08x\n", base, max); uint32_t baseDiff = 0; if( base == 0 ) { // Find a nice space (47 address bits allowed) base = FindFreeRange( max, 47 ); LOG("new base = %08x\n", base); if( base == 0 ) return NULL; baseDiff = base; } // Load Pages for( unsigned int i = 0; i < hdr->e_phnum; i++ ) { // Get Interpreter Name if( phtab[i].p_type == PT_INTERP ) { char *tmp; //if(ret->Interpreter) continue; tmp = malloc(phtab[i].p_filesz); acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET); acess__SysRead(FD, tmp, phtab[i].p_filesz); //ret->Interpreter = Binary_RegInterp(tmp); LOG("Interpreter '%s'\n", tmp); free(tmp); continue; } // Ignore non-LOAD types if(phtab[i].p_type != PT_LOAD) continue; LOG("phtab[%i] = PT_LOAD {Adj p_vaddr:0x%x, p_offset:0x%x, p_filesz:0x%x, p_memsz:0x%x}\n", i, phtab[i].p_vaddr+baseDiff, phtab[i].p_offset, phtab[i].p_filesz, phtab[i].p_memsz); uint64_t addr = phtab[i].p_vaddr + baseDiff; if( AllocateMemory( addr, phtab[i].p_memsz ) ) { fprintf(stderr, "Elf_Load: Unable to map memory at 0x%"PRIx64" (0x%x bytes)\n", addr, phtab[i].p_memsz); free( phtab ); return NULL; } acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET); acess__SysRead(FD, PTRMK(void, addr), phtab[i].p_filesz); memset( PTRMK(char, addr) + phtab[i].p_filesz, 0, phtab[i].p_memsz - phtab[i].p_filesz ); } // Clean Up free(phtab); // Return LEAVE('p', base); return PTRMK(void, base); }