#!/usr/bin/env python

import struct

class PagedOutException(Exception):
    pass

def virt2phys(memdump, pdb_addr, virt_addr):
    """Convert a virtual address to a physical one.
    As this cannot be done without a valid Page Directory, the user must
    provide one as an argument. This function throws a PagedOutException
    if the entry in the Page Directory is marked not valid, since in this
    case the physical address in memory cannot be determined.

    Arguments:

    memdump: file object in which the Page Directory exists
    pdb_addr: the offset in the memory dump where the PDB can be found
    virt_addr: the virtual address to be converted, as an int"""

    orig_off = memdump.tell()
    
    pd_offset = ((virt_addr & 0xFFC00000) >> 22)*4
    pt_offset = ((virt_addr & 0x003FF000) >> 12)*4
    b_offset  = (virt_addr &  0x00000FFF)

    memdump.seek(pdb_addr+ pd_offset)
    pdemember = struct.unpack('<L', memdump.read(4))[0]
    if pdemember & 1 == 0:
        raise PagedOutException()
    pt_off =  pdemember & 0xFFFFF000

    memdump.seek(pt_off + pt_offset)
    ptemember = struct.unpack('<L', memdump.read(4))[0]
    phys_addr =  (ptemember & 0xFFFFF000) + b_offset
    
    memdump.seek(orig_off)
    return phys_addr
