[ create a new paste ] login | about

Link: http://codepad.org/c0JO0SBv    [ raw code | output | fork ]

Python, pasted on Sep 11:
import ctypes, mmap, struct
try:
    _VirtualAlloc = ctypes.windll.kernel32.VirtualAlloc
    def valloc(size): 
        addr = _VirtualAlloc(0, size, 0x1000, 0x40)
        if not addr:
            raise RuntimeError("Cannot allocate RWX memory")
        return addr
except:
    libc = ctypes.CDLL("libc.so.6")
    def valloc(size):
        addr = libc.valloc(size)
        if not addr or libc.mprotect(addr, size, 0x07):
            raise RuntimeError("Cannot allocate RWX memory")
        return addr

class RPN_jit:
    def __init__(self):
        self.size = mmap.PAGESIZE
        self.exepage = valloc(self.size) # a single page for execution at the very minimum
    def emit(self, code):
        # we will use cdecl function declarations, assume small endianness
        buffer = "\x55" + "\x8b\xec" + "\x81\xec\xcc\0\0\0" + "\x53" + "\x56" + "\x57" + "\x8d\xbd\x34\xff\xff\xff"
        def _num(o): 
            try: return int(o)
            except: return int(o, 16)
        sp = 0 # stack count, used to clean up stack space
        for o in code.split():
            # valid tokens: integers, +, -, *, /, %; all operators are assumed binary
            try:
                o = _num(o)
                # eax, ecx serves as our registers for most current values, the stack comes later
                # every time we load in an integer, effectively, we push the content of ecx, bump eax's data into ecx, and then load into eax
                buffer += "\x51"+"\x91"+"\xb8"+struct.pack("i",o&(0xffffffff)) # don't want to overflow the mov instruction
                sp+=1
            except (ValueError):
                # eax is first param, ecx is second param, eax is storage, and then we pop into ecx
                # at the end of the run, eax is the most recently "pushed" item, perfect for /xc3
                if sp<2: raise RuntimeError("Stack will underflow.")
                buffer += "\x03\xc1" if o in ("+", "add", "plus") else "\x2b\xc1" if o in ("-", "sub", "minus") \
                    else "\x0f\xaf\xc1" if o in ("*", "mul", "mult") else "\x99\xf7\xf9" if o in ("/", "div") \
                    else "\x99\xf7\xf9\x92" if o in ("%", "mod", "rem") else "\x55" # mod is actually just idiv and xchg edx, eax
                buffer += "\x59" # pop ecx
                sp-=1
        if not sp: raise RuntimeError("Nothing to compile.")
        for _ in range(sp): buffer += "\x59" # pop ecx to clear the stack
        buffer += "\x5f\x5e\x5b\x8b\xe5\x5d\xc3" # pops all register, rebases ebp&esp, and return eax, which contains the last push
        if not ctypes.memmove(self.exepage, buffer, min(len(buffer), self.size)):
            raise RuntimeError("Input cannot not fit into memory.")
        return ctypes.CFUNCTYPE(ctypes.c_int32)(self.exepage)
        
a = RPN_jit()
print a.emit("3 10 mod 10 + 0x100 * 100 * 50 +")()


Output:
1
281650


Create a new paste based on this one


Comments: