def big(n, len):
    bytes = ""
    while len > 0:
        bytes = chr (n & 255) + bytes
        n >>= 8
        len = len - 1
    return bytes

def strtohex (str):
    hex=""
    for c in str:
        hex = hex + ("%02x" % ord (c))
    return hex

def send (cmd):
    f = file ("/proc/gdb-tracepoints", "w")
    f.write (cmd)
    f.close ()
    f = file ("/proc/gdb-tracepoints", "r")
    response = f.read ()
    f.close ()
    return response

def start():
    return send ("QTStart")

def stop():
    return send ("QTStop")

def init():
    return send ("QTinit")

def points():
    return send ("points")

def hits():
    return send ("hits")


class expr:

    def __init__(self):
        self.bytes = ""

    def add(self):           self.bytes = self.bytes + chr (0x02); return self
    def sub(self):           self.bytes = self.bytes + chr (0x03); return self
    def mul(self):           self.bytes = self.bytes + chr (0x04); return self
    def div_signed(self):    self.bytes = self.bytes + chr (0x05); return self
    def div_unsigned(self):  self.bytes = self.bytes + chr (0x06); return self
    def rem_signed(self):    self.bytes = self.bytes + chr (0x07); return self
    def rem_unsigned(self):  self.bytes = self.bytes + chr (0x08); return self
    def lsh(self):           self.bytes = self.bytes + chr (0x09); return self
    def rsh_signed(self):    self.bytes = self.bytes + chr (0x0a); return self
    def rsh_unsigned(self):  self.bytes = self.bytes + chr (0x0b); return self

    def log_not(self):       self.bytes = self.bytes + chr (0x0e); return self
    def bit_and(self):       self.bytes = self.bytes + chr (0x0f); return self
    def bit_or(self):        self.bytes = self.bytes + chr (0x10); return self
    def bit_xor(self):       self.bytes = self.bytes + chr (0x11); return self
    def bit_not(self):       self.bytes = self.bytes + chr (0x12); return self
    def equal(self):         self.bytes = self.bytes + chr (0x13); return self
    def less_signed(self):   self.bytes = self.bytes + chr (0x14); return self
    def less_unsigned(self): self.bytes = self.bytes + chr (0x15); return self

    def ref8(self):          self.bytes = self.bytes + chr (0x17); return self
    def ref16(self):         self.bytes = self.bytes + chr (0x18); return self
    def ref32(self):         self.bytes = self.bytes + chr (0x19); return self
    def ref64(self):         self.bytes = self.bytes + chr (0x1a); return self

    def end(self):           self.bytes = self.bytes + chr (0x27); return self
    def dup(self):           self.bytes = self.bytes + chr (0x28); return self
    def pop(self):           self.bytes = self.bytes + chr (0x29); return self

    def swap(self):          self.bytes = self.bytes + chr (0x2b); return self

    def ext(self, n):
        assert 0 <= n and n <= 255
        self.bytes = self.bytes + chr (0x16) + chr (n)
        return self
    def zero_ext(self, n):
        assert 0 <= n and n <= 255
        self.bytes = self.bytes + chr (0x2a) + chr (n)
        return self

    def trace(self):
        self.bytes = self.bytes + chr (0x0c)
        return self
    def trace_quick(self, n):
        assert 0 <= n and n <= 255
        self.bytes = self.bytes + chr (0x0d) + chr (n)
        return self
    def trace16(self, n):
        assert 0 <= n and n <= 65535
        self.bytes = self.bytes + chr (0x30) + big (n, 2)
        return self

    def if_goto(self, n):
        assert 0 <= n and n <= 65535
        self.bytes = self.bytes + chr (0x20) + big (n, 2)
        return self
    def goto(self, n):
        assert 0 <= n and n <= 65535
        self.bytes = self.bytes + chr (0x21) + big (n, 2)
        return self

    def const8(self, n):
        assert -128 <= n and n <= 255
        self.bytes = self.bytes + chr (0x22) + big (n, 1)
        return self
    def const16(self, n):
        assert -0x8000 <= n and n <= 0xffff
        self.bytes = self.bytes + chr (0x23) + big (n, 2)
        return self
    def const32 (self, n):
        assert -0x80000000 <= n and n <= 0xffffffff
        self.bytes = self.bytes + chr (0x24) + big (n, 4)
        return self
    def const64(self, n):
        assert -(1 << 63) <= n and n <= (1 << 64) - 1
        self.bytes = self.bytes + chr (0x25) + big (n, 8)
        return self

    def reg(self, n):
        assert 0 <= n and n <= 65535
        self.bytes = self.bytes + chr (0x26) + big (n, 2)
        return self

class tp:
    
    def __init__(self, num, addr, pass_count=100, step_count=0):
        self.num = num
        self.addr = addr
        self.pass_count = pass_count
        self.step_count = step_count
        self.enabled = True;
        self.exprs = []
        self.ranges = []

    def expr (self):
        new = expr ()
        self.exprs.append (new)
        return new

    def range (self, offset, len, basereg=None):
        self.ranges.append ((basereg, offset, len))
        return self

    def deftp(self):
        if (self.enabled):
            e = "E"
        else:
            e = "D"
        print send ("QTDP:%x:%x:%s:%x:%x"
                     % (self.num, self.addr, e, 
                        self.step_count, self.pass_count))
        for expr in self.exprs:
            bytes = expr.bytes
            print send ("QTDP:-%x:%x:X%x,%s"
                        % (self.num, self.addr,
                           len (bytes), strtohex (bytes)))
        for range in self.ranges:
            (basereg, offset, length) = range
            if basereg:
                baseregstr = "%x" % (basereg)
            else:
                baseregstr = "-1"
            print send ("QTDP:-%x:%x:M%s,%x,%x"
                        % (self.num, self.addr, baseregstr, offset, length))
                           

vfs_read = 0xc0475e7c
vfs_write = 0xc0475d22
sys_symlinkat = 0xc047e882


t1 = tp (1, vfs_read, 5)
t1.expr ().const8(2).const8(2).add().end()

t2 = tp (2, vfs_write, 5)
t2.expr ().const8(4).const8(4).add().end()
t2.expr ().reg(4).trace_quick(20).end()

t3 = tp (3, sys_symlinkat + 39);
t3.expr ().reg(0).const8(4).add().trace_quick(4).end()
t3.expr ().reg(0).trace_quick(4).end()

t4 = tp (4, 42)
t4.enabled = False
t4.range (1000,10)
t4.range (2000,20,4)

t5 = tp (5, vfs_read, 5)
t5.expr ().const8(0).ref8().end()
