// $Id: read_pgd.c,v 1.4 2004/11/03 11:42:39 kaiya Exp $ #define __KERNEL__ #define SEEK_SET 0 #include #include #include #define pidhash_addr 0xc032d8a0 void readkmem(int fd, void *buf, unsigned off, int sz) { if(lseek(fd, off, SEEK_SET) != off){ perror("kmen lseek"); exit(1); } if(read(fd, buf, sz) != sz){ perror("kmen read"); exit(1); } } void find_task(int fd, int pid, struct task_struct* task) { struct task_struct *htable_ptr; readkmem(fd, &htable_ptr, pidhash_addr + (pid_hashfn(pid)*4), sizeof(htable_ptr)); while(1){ readkmem(fd, task, (unsigned)htable_ptr, sizeof(*task)); if(pid == task->pid){ return; } htable_ptr=task->next_task; } } void print_pte(int fd, pgd_t pgd, unsigned pgd_index) { pte_t pgt[1024]; int i; unsigned vaddr = pgd_index << PGDIR_SHIFT; unsigned pte_addr = pgd_val(pgd) & PAGE_MASK; /* 4MB page */ if(pgd_val(pgd) & _PAGE_PSE){ printf("%08x -- %08x m -> [%s%s] %08x\n", vaddr, vaddr + 4*1024*1024-1, (pgd_val(pgd) & _PAGE_USER)? "U": " ", (pgd_val(pgd) & _PAGE_RW)? "W": " ", pte_addr ); } /* 4KB page */ else { /* read page table */ readkmem(fd, pgt, (unsigned)pte_addr, sizeof(pgt)); for(i=0; i<1024; i++){ pte_t pte=pgt[i]; if(!pte_none(pte)){ unsigned page_addr = pte_val(pte) & PAGE_MASK; printf("%08x -- %08x k -> [%s%s] ", vaddr + (i << PAGE_SHIFT), vaddr + (i << PAGE_SHIFT) + 4*1024-1, (pgd_val(pgd) & _PAGE_USER)? "U": " ", (pgd_val(pgd) & _PAGE_RW)? "W": " " ); if(pte_val(pte) & _PAGE_PRESENT){ printf("[%s%s] %08x\n", (pgd_val(pgd) & _PAGE_USER)? "U": " ", (pgd_val(pgd) & _PAGE_RW)? "W": " ", page_addr ); }else{ printf(" page out\n"); } } } } } main(int argc, char* argv[]){ pgd_t pgd[1024]; int i, kmemfd, memfd; struct task_struct task; struct mm_struct mm; int pid; if(argc != 2){ printf("%s pid\n", argv[0]); exit(1); } pid=atoi(argv[1]); if(pid < 1){ printf("Invalid pid %d\n", pid); exit(1); } kmemfd = open("/dev/kmem", O_RDONLY); if(kmemfd < 0){ perror("kmem open"); exit(1); } memfd = open("/dev/mem", O_RDONLY); if(memfd < 0){ perror("mem open"); exit(1); } /* find a task struct from pidhash table */ find_task(kmemfd, pid, &task); if(task.pid != pid){ printf("pid not found %d\n", pid); exit(1); } /* read mm_struct */ readkmem(kmemfd, &mm, (unsigned)task.active_mm, sizeof(mm)); /* read page directory */ readkmem(kmemfd, pgd, (unsigned)mm.pgd, sizeof(pgd)); printf(" Virtual Address t PGD PTE Physical Address\n"); printf("----------------------------------------------\n"); for(i=0; i<1024; i++){ if(pgd_val(pgd[i]) & _PAGE_PRESENT){ print_pte(memfd, pgd[i], i); } } return 0; }