import gdb
import os
import struct


def libpoplar_base():
    pid = gdb.selected_inferior().pid
    with open("/proc/%d/maps" % pid) as mappings:
        for line in mappings:
            if "libpoplar.so" in line and "r-xp" in line:
                start = int(line.split("-", 1)[0], 16)
                offset = int(line.split()[2], 16)
                return start - offset
    raise gdb.GdbError("libpoplar.so is not mapped")


class Capture(gdb.Breakpoint):
    def __init__(self, address, output):
        super().__init__("*0x%x" % address, internal=False)
        self.output = output
        self.records = []

    def stop(self):
        offset = int(gdb.parse_and_eval("$rsi")) & 0xffffffff
        value = int(gdb.parse_and_eval("$rdx")) & 0xffffffff
        if offset == 0x2068:
            with open(self.output, "wb") as output:
                output.write(b"IPUCFG1\0")
                output.write(struct.pack("<I", len(self.records)))
                for record in self.records:
                    output.write(struct.pack("<II", *record))
            gdb.write("captured %u writes in %s\n" %
                      (len(self.records), self.output))
            self.enabled = False
        else:
            self.records.append((offset, value))
        return False


base = libpoplar_base()
output = os.environ.get("IPU_CONFIG_CAPTURE", "/tmp/c600-init.ipucfg")
Capture(base + 0x3C6C7A0, output)
