DWORD xmaplineartophysical(const DWORD linearmemory,const DWORD physicalmemory, DWORD *pagedir,const DWORD attb) //ATOMIC { DWORD w=linearmemory; DWORD dirindex=(w&0xFFC00000) >> 22; DWORD pageindex=(w&0x3FF000) >> 12; DWORD *pagetbl; DWORD flags; dex32_stopints(&flags); disablepaging(); if (pagedir[dirindex]&PG_PRESENT==0) //no page table allocated? { pagetbl=mempop(); if (pagetbl==0) {dex32_restoreints(flags);enablepaging();return 0;}; pagedir[dirindex]=(DWORD)pagetbl | 1; }; if (pagedir[dirindex]&1) { pagetbl=(DWORD*)(pagedir[dirindex]&0xFFFFF000); pagetbl[pageindex]=physicalmemory | (attb&0xFFF); dex32_restoreints(flags); enablepaging(); return 1; } dex32_restoreints(flags); enablepaging(); return 0; };
/* This function maps the linear address to a physical address: The function automatically allocates a page for a page table the bottom 12 bits of the linear address is discarded since it is not used by the mapper*/ void maplineartophysical(unsigned int *pagedir, /*the location of the page directory*/ unsigned int linearaddr, /*the paged aligned linear address requested*/ unsigned int physical, /*the paged aligned physical address to map to*/ unsigned int attribute /*used to specify the page attributes to be applied*/ ) { unsigned int pagedirindex,pagetableindex,*pagetable; /*get the index of the page directory and the pagetable respectively*/ pagedirindex= linearaddr >> 22; pagetableindex= (linearaddr & 0x3FFFFF) >> 12; /*get the location of the page table and mask the first 12 bits*/ pagetable=(unsigned int*)(pagedir[pagedirindex] & 0xFFFFF000); if (pagetable==0) /*there is no entry?*/ { /*map a new memory location*/ pagedir[pagedirindex]=(DWORD) mempop(); pagetable=(unsigned int*)pagedir[pagedirindex]; /*clear the locations of the page table to zero*/ memset(pagetable,0,4096); /*set the present bit of the pagetable dir entry*/ pagedir[pagedirindex]=pagedir[pagedirindex] | 1 | PG_USER | PG_WR; }; physical=(physical & 0xFFFFF000) | attribute; pagetable[pagetableindex]=physical; /*done!*/ };
void exec(b32 *filename) { b32 pcb_; b32 page; asm volatile( "jmp . \n\t" ::: ); procpop(&pcb_); getpageaddr(PCBAddr,pcb_,0x4c,&page); //需要pcb块大小 initpage(page); PCB * pcb=(PCB *)pcb_; printdword((b32)(pcb)); pcb->esp=0x13FFFF0; pcb->status=READY; pcb->cr3=page; pcb->pid=(*(b32 *)PID)+4; pcb->edi=0; pcb->esi=0; pcb->ebx=0; pcb->edx=0; pcb->eflags=0; pcb->ss=user_stack; pcb->cs=user_code; pcb->eip=0; *(b32 *)PID=*(b32 *)PID+4; b32 phymem; filename[11]=0; //得到格式化后的文件名 mempop(&phymem); readfile(filename,phymem); linkpage(pcb->cr3,0x1000000,phymem); quenein(READYAddr,READYBottom,READYhead,READYtail,pcb_); }
/*same as map linear to physical except that it does its tricks without modifying the paging bit */ int maplineartophysical2(unsigned int *pagedir, /*the location of the page directory*/ unsigned int linearaddr, /*the paged aligned linear address requested*/ unsigned int physical, /*the paged aligned physical address to map to*/ unsigned int attribute /*used to specify the page attributes to be applied*/ ) { unsigned int pagedirindex,pagetableindex,*pagetable; DWORD pg; DWORD *kicker=(DWORD*)SYS_PAGEDIR2_VIR; /*get the index of the page directory and the pagetable respectively*/ pagedirindex= linearaddr >> 22; pagetableindex= (linearaddr & 0x3FFFFF) >> 12; /*get the location of the page table and mask the first 12 bits*/ pg=(pagedir[pagedirindex] & 0xFFFFF000); if (pg==0) /*there is no entry?*/ { /*map a new memory location*/ pagedir[pagedirindex]=(DWORD) mempop(); kicker[4]=(pagedir[pagedirindex]&0xFFFFF000) | 1; refreshpages(); pagetable=(DWORD*)SYS_PAGEDIR4_VIR; tlb_address = pagetable; invtlb(); /*clear the locations of the page table to zero*/ memset(pagetable,0,4096); /*set the present bit of the pagetable dir entry*/ pagedir[pagedirindex] = pagedir[pagedirindex] | 1 | PG_USER | PG_WR; refreshpages(); pg = (pagedir[pagedirindex] & 0xFFFFF000); }; kicker[4]=pg | 1; refreshpages(); pagetable=(DWORD*)SYS_PAGEDIR4_VIR; physical = (physical & 0xFFFFF000) | attribute; pagetable[pagetableindex]=physical; refreshpages(); tlb_address = linearaddr; invtlb(); /*done!*/ };
//duplicates a process using COPY_ON_WRITE methods *NOT YET WORKING!!* DWORD forkprocess(PCB386 *parent) { int pages; DWORD *pagedir,pg,flags; DWORD parentpd = parent->pagedirloc; PCB386 *pcb = (PCB386*) malloc(sizeof(PCB386)); #ifdef DEBUG_FORK printf("fork process has been called.\n"); #endif dex32_stopints(&flags); memcpy(pcb,parent,sizeof(PCB386)); strcat(pcb->name,".fork"); totalprocesses++; pcb->size = sizeof(PCB386); pcb->processid = nextprocessid++; pcb->owner = parent->processid; /*Allocate a new page directory*/ pagedir=(DWORD*)mempop(); //obtain a physical address from the memory manager pg=(DWORD*)getvirtaddress((DWORD)pagedir); //convert physical address to a virtual address //initialize the new pagedirectory memset(pg,0,0x1000); pcb->regs.CR3 = pagedir; pcb->pagedirloc = pagedir; #ifdef DEBUG_FORK printf("copying memory..\n"); #endif disablepaging(); dex32_copy_pg(pagedir,parentpd); maplineartophysical((DWORD*)pagedir,(DWORD)SYS_PAGEDIR_VIR,(DWORD)pagedir /*,stackbase*/,1); maplineartophysical((DWORD*)pagedir,(DWORD)SYS_PAGEDIR2_VIR, (DWORD)pagedir[SYS_PAGEDIR_VIR >> 22]&0xFFFFF000,1); maplineartophysical((DWORD*)pagedir,(DWORD)SYS_PAGEDIR3_VIR, (DWORD)pagedir[SYS_PAGEDIR_VIR >> 22]&0xFFFFF000,1); maplineartophysical((DWORD*)pagedir,(DWORD)SYS_KERPDIR_VIR,(DWORD)pagedir1 /*,stackbase*/,1); enablepaging(); #ifdef DEBUG_FORK printf("done. adding to process queue\n"); #endif //copies the memory allocation information of the parent to the child //(forked processes have the same virtual memory map at time of fork) copyprocessmemory(parent->meminfo,&pcb->meminfo); //add to the process list ps_enqueue(pcb); dex32_restoreints(flags); #ifdef DEBUG_FORK printf("fork done.\n"); #endif return pcb->processid; };
void * memalloc(size_t nb, long flg) { struct mempool *physpool = &memphyspool; struct mempool *virtpool = &memvirtpool; struct memmag **magtab = (struct maghdr **)virtpool->tab; void *ptr = NULL; size_t sz = max(MEMMIN, nb); size_t bsz; unsigned long slab = 0; unsigned long bkt = memcalcbkt(sz); #if defined(MEMPARANOIA) unsigned long *bmap; #endif struct memmag *mag; uint8_t *u8ptr; unsigned long ndx; unsigned long n; struct membkt *hdr = &virtpool->tab[bkt]; mtxlk(&hdr->lk); if (bkt >= MEMSLABMINLOG2) { ptr = slaballoc(physpool, sz, flg); if (ptr) { #if (!MEMTEST) vminitvirt(&_pagetab, ptr, sz, flg); #endif slab++; mag = memgetmag(ptr, virtpool); mag->base = (uintptr_t)ptr; mag->n = 1; mag->ndx = 1; mag->bkt = bkt; mag->prev = NULL; mag->next = NULL; } } else { mag = magtab[bkt]; if (mag) { ptr = mempop(mag); if (memmagempty(mag)) { if (mag->next) { mag->next->prev = NULL; } magtab[bkt] = mag->next; } } else { ptr = slaballoc(physpool, sz, flg); if (ptr) { #if (!MEMTEST) vminitvirt(&_pagetab, ptr, sz, flg); #endif u8ptr = ptr; slab++; bsz = (uintptr_t)1 << bkt; n = (uintptr_t)1 << (MEMSLABMINLOG2 - bkt); mag = memgetmag(ptr, virtpool); mag->base = (uintptr_t)ptr; mag->n = n; mag->ndx = 1; mag->bkt = bkt; for (ndx = 1 ; ndx < n ; ndx++) { u8ptr += sz; mag->ptab[ndx] = u8ptr; } mag->prev = NULL; mag->next = NULL; if (n > 1) { mag->next = magtab[bkt]; magtab[bkt] = mag; } } } } if (ptr) { #if defined(MEMPARANOIA) #if ((MEMSLABMINLOG2 - MEMMINLOG2) < (LONGSIZELOG2 + 3)) bmap = &mag->bmap; #else bmap = mag->bmap; #endif ndx = ((uintptr_t)ptr - mag->base) >> bkt; if (bitset(bmap, ndx)) { kprintf("duplicate allocation %p (%ld/%ld)\n", ptr, ndx, mag->n); panic(k_curproc->pid, TRAPNONE, -EINVAL); } setbit(bmap, ndx); #endif /* defined(MEMPARANOIA) */ if (!slab && (flg & MEMZERO)) { kbzero(ptr, 1UL << bkt); } } if (!ptr) { panic(k_curproc->pid, TRAPNONE, -ENOMEM); } mtxunlk(&hdr->lk); return ptr; }
int coff_loadusermodule( char *module_name, //the name of the module char *coff_image, //the location of the pe image DWORD base, //the desired base address to load the image so //that dex can perform the necessary relocations int mode, //Determines what kind of executable to load char *p, //the parameters char *workdir, PCB386 *parent //the parent PCB for EXEs, the parent pagedirectory for DLLs ) //location of image to load { char temp[255],temp2[255]; FILHDR *fhdr = (FILHDR*) coff_image; //a linked list used to keep track of the virtual addresses used //by this process so that it could be freed when the process //terminates process_mem *tmpr,*memptr; //validate if this file is a coff format executable #ifdef DEBUG_COFF printf("dex32_coff_loader: started\n"); printf("dex32_coff_loader: magic number obtained [%s]\n",itoa(fhdr->f_magic,temp,16)); #endif if (fhdr->f_magic==I386MAGIC) { int i; AOUTHDR *aouthdr = (AOUTHDR*)(coff_image + sizeof(FILHDR)); SCNHDR *section = (SCNHDR*)((DWORD)coff_image + sizeof(FILHDR)+sizeof(AOUTHDR)); SYMENT *symbols = fhdr->f_symptr; int totalsymbols = fhdr->f_nsyms; DWORD *pagedir,*pg; DWORD heapres=0,stackres=0; DWORD *stackloc; DWORD flags,pages,ret; int totalsections = fhdr->f_nscns; void (*entrypoint)(int,char**)=0; #ifdef DEBUG_COFF printf("dex32_coff_loader: magic number 2 obtained [%s]\n",itoa(aouthdr->magic,temp,16)); #endif if (aouthdr->magic!=ZMAGIC) return 0; //check again printf("dex32_coff_loader: loading executable..\n"); #ifdef DEBUG_COFF printf("dex32_coff_loader: entry point at %sH\n",itoa(aouthdr->entry,temp,16)); printf("dex32_coff_loader: Total sections %d\n",totalsections); #endif entrypoint=(void*) aouthdr->entry; if (fhdr->f_flags&F_RELFLG) { printf("dex32_coff_loader: Relocations have been stripped of the file\n"); }; memptr=(process_mem*)malloc(sizeof(process_mem)); tmpr=memptr; pagedir=(DWORD*)mempop(); //obtain a physical address from the memory manager pg=(DWORD*)getvirtaddress((DWORD)pagedir); //convert to a virtual address so that //we could use it here without disabling //the paging mechanism of the 386 //initialize the new pagedirectory memset(pg,0,0x1000); stackloc=(DWORD*)dex32_commitblock((DWORD)userstackloc-1000, 1000,&pages, pagedir,PG_WR | PG_USER | PG_PRESENT); //take note of this so that we could free it later tmpr->vaddr=(DWORD)stackloc; tmpr->pages=pages; tmpr->next=(process_mem*)malloc(sizeof(process_mem)); tmpr=tmpr->next; tmpr->vaddr=0;tmpr->next=0; //allocate the "reserve" user stack //this pages don't get a physical memory until it actually gets //accessed stackres=dex32_reserveblock((DWORD)stackloc-DEFAULT_STACKSIZE, DEFAULT_STACKSIZE,&pages,pagedir,PG_WR); //store the allocation information so that it could be linked to //the process PCB and then be able to free up the memory when app terminates tmpr->vaddr=(DWORD)stackres; tmpr->pages=pages; //create another node in the linked list tmpr->next=(process_mem*)malloc(sizeof(process_mem)); tmpr=tmpr->next; tmpr->vaddr=0;tmpr->next=0; //calculate the position of the ESP pointer stackloc = userstackloc - 4 ; //allocate "commited" user heap //unlike the stack, this one goes up dex32_commitblock((DWORD)userheap,1000,&pages, pagedir,PG_WR | PG_USER | PG_PRESENT); //take note of this, so that it wouldn't cause a memory leak later tmpr->vaddr=(DWORD)userheap; tmpr->pages=pages; tmpr->next=(process_mem*)malloc(sizeof(process_mem)); tmpr=tmpr->next; tmpr->vaddr=0;tmpr->next=0; //calculate the position of the reserved heap heapres=userheap+(pages*0x1000); //allocate "reserved" user heap dex32_reserveblock((DWORD)heapres, DEFAULT_HEAPSIZE,&pages,pagedir,PG_WR ); tmpr->vaddr=(DWORD)heapres; tmpr->pages=pages; tmpr->next=(process_mem*)malloc(sizeof(process_mem)); tmpr=tmpr->next; tmpr->vaddr=0;tmpr->next=0; //examine the sections for (i=0;i<totalsections;i++) { int i2; char section_name[256]; DWORD rawdata, vaddr,size,pages,relnum; RELOC *relocation; /* copy the name of the section to a temporary vriable */ for (i2=0; section[i].s_name[i2]&&i2<8;i2++) { section_name[i2] = section[i].s_name[i2]; }; section_name[i2]=0; /*null terminator*/ rawdata = section[i].s_scnptr; //pointer to raw data in file vaddr = section[i].s_vaddr; //absolute address in memory size = section[i].s_size; //size of the section relocation = (RELOC*)section[i].s_relptr; //relocation pointer relnum = section[i].s_nreloc; //number of relocations #ifdef DEBUG_COFF printf("dex32_coff_loader: Section name [%s]\n",section_name); printf("dex32_coff_loader: ** file offset [%d]\n",rawdata); printf("dex32_coff_loader: ** load at [%sH]\n",itoa(vaddr,temp,16)); #endif /*perform relocations*/ for (i2=0;i2<relnum;i2++) { if (relocation[i2].r_type==RELOC_ADDR32) { DWORD *loc=symbols[relocation[i2].r_symndx].e_value; printf("dex32_coff_loader: ABSOLUTE RELOCATION Detected\n"); } else if (relocation[i2].r_type==RELOC_REL32) { printf("dex32_coff_loader: RELATIVE RELOCATION Detected\n"); } else printf("dex32_coff_loader: UNKNOWN RELOCATION TYPE\n"); }; /*allocate physical memory and assign a virtual address*/ #ifdef DEBUG_COFF printf("dex32_coff_loader: Commiting block..\n"); #endif tmpr->vaddr=(DWORD)dex32_commitblock((DWORD)base+vaddr,size,&pages, pagedir,PG_WR | PG_USER | PG_PRESENT); #ifdef DEBUG_COFF printf("dex32_coff_loader: Copying image at %s to %s..\n", itoa(coff_image+rawdata,temp2,16),itoa(tmpr->vaddr,temp,16)); #endif //copy the section to main memory memcpy(tmpr->vaddr,coff_image+rawdata,size); #ifdef DEBUG_COFF printf("dex32_coff_loader: ***Done***\n"); #endif //take note of the memory used so that we could free it up later tmpr->pages=pages; tmpr->next=(process_mem*)malloc(sizeof(process_mem)); tmpr=tmpr->next; tmpr->vaddr=0;tmpr->next=0; }; dex32_stopints(&flags); ret=createprocess(entrypoint,module_name,pagedir,memptr,stackloc, 1000,0x2000,signal,p,workdir,parent); dex32_restoreints(flags); dex32_freeuserpagetable(pagedir1); return ret; }; return 0; //not a coff file or error loading file };