# Path: fiddle/staticanalysis.py
# class LongWriteInfo():
#     def __init__(self, elf, start, end, thumb):
#         r2.run_aab(elf) # run basic block analysis
#         self.valid = True
#         self.start_ins = None
#         self.start_ins_addr = None
#         self.write_ins = None
#         self.write_ins_addr = None
#         self.finish_ins = None
#         self.finish_ins_addr = None
#         self.start = start
#         self.end = end
#         self.elf = elf
#         self.thumb = thumb
#         self.valid = False
#         self.branch_ins_addr = None
#         self.branch_ins = None
#         # grab basic blocks surrounding this region
#         r2.gets(elf, "s 0x%x" % self.start)
#         if self.thumb:  # force r2 to use the correct instruction size. sigh.
#             r2.gets(elf, "ahb 16")
#             r2.gets(elf, "e asm.bits=16")
#         else:
#             r2.gets(elf, "ahb 32")
#             r2.gets(elf, "e asm.bits=32")
#         self.bbs = r2.get(elf, "pdbj")
#         next = self.bbs[-1]["offset"] + self.bbs[-1]["size"]
#         while next < end:
#             r2.get(elf, "s 0x%x" % next)
#             self.bbs.extend(r2.get(elf, "pdbj"))
#             next = self.bbs[-1]["offset"] + self.bbs[-1]["size"]
#         # grab one more basic block
#         r2.get(elf, "s 0x%x" % next)
#         self.bbs.extend(r2.get(elf, "pdbj"))
# 
#     def calculate_info(self):
#         # lookup write instruction
#         nwrites = 0
#         elf = self.elf
#         for i in self.bbs:
#             mne = i["opcode"].split()[0]
#             if InstructionAnalyzer._is_mne_memstore(mne):
#                 nwrites += 1
#                 if (self.start <= i["offset"]) and (i["offset"] <= self.end):
#                     if self.write_ins is not None:
#                         # if there are two write instruction in basic block, don't know what to do
#                         self.valid = False
#                         break
#                     else:
#                         self.write_ins = i
#                         self.valid = True
#                         self.write_ins_addr = self.write_ins["offset"]
#         if nwrites > 1:
#             print "Warning: %s write ins in these blocks" % nwrites
# 
#         if not self.valid:
#             return
# 
#         # look for branch after write to find loop
#         branch = None
#         unconditional = False
#         for b in self.bbs:
#             if b["offset"] < self.write_ins_addr:
#                 continue
#             if b["type"] == u"cjmp" or b["type"] == u"jmp":
#                 if b["type"] == "jmp":
#                     dst = b["jump"]
#                     r2.gets(elf, "s 0x%x" % dst)
#                     for next in r2.get(elf, "pdbj"):
#                         if next["type"] == u"cjmp" or next["type"] == "jmp":
#                             if next["type"] == "cjmp":
#                                 jump = next["jump"]
#                                 if jump not in [ii["offset"] for ii in self.bbs]:
#                                     self.finish_ins_addr = jump
#                                 else:
#                                     self.finish_ins_addr = next["offset"] + next["size"]
#                             else:
#                                 # don't handle this case yet
#                                 self.valid = False
#                             break
#                     break
#                     #branch = r2.get(elf, "pdj 1")[0]
#                     #self.finish_ins_addr = branch["offset"] + branch["size"]
#                 else:
#                     branch = b
#                     jump = branch["jump"]
#                     if jump not in [ii["offset"] for ii in self.bbs]:
#                         self.finish_ins_addr = jump
#                     else:
#                         self.finish_ins_addr = branch["offset"] + branch["size"]
# 
#         r2.gets(elf, "s 0x%x" % self.finish_ins_addr)
#         self.finish_ins = r2.get(elf, "pdj 1")[0]
#         self.start_ins_addr = self.write_ins_addr
#         self.start_ins = self.write_ins
# 
#     def __repr__(self):
#         if not self.valid:
#             return "<invalid longwrite @ 0x%x>" % self.start_ins_addr
#         else:
#             return "<longwrite [start=0x%x,write=0x%x,done=0x%x]>" % (self.start_ins_addr, self.write_ins_addr, self.finish_ins_addr)


import fiddle.staticanalysis
import fiddle.r2_keeper as r2
import sys
from fiddle.staticanalysis import LongWriteInfo
            return "<invalid longwrite @ 0x%x>" % self.start_ins_addr
        else:
            return "<longwrite [start=0x%x,write=0x%x,done=0x%x]>" % (self.start_ins_addr, self.write_ins_addr, self.finish_ins_addr)

#    def __repr__(self):
#        return str(self)

def longwrite_info(elf, addr, thumb):
    l = LongWriteInfo(elf, start, end, thumb)
    return l

def analyze(elf):
    r2.get(elf, "aas")
    tsts = [(0x40208b6e, True),
             (0x402025c0, False), # bss
             (0x40208b24, True), # memset
            # (0x40208b30, True), # memset, just 8 bits at most
             (0x40208b50, True), # memcpy
            (0x40206de0, True)] # mmc_read_data

    #for i in tsts:
    #    l = longwrite_info(elf, i[0], i[1])
    #    print l

    tsts = [(0x40208b1e, 0x40208b20, True), # memset
            (0x40208b50, 0x40208b54, True), # memcpy
            (0x40206dd6, 0x40206dde, True), # mmc_read_data
            (0x402025c4, 0x402025c8, False) # clearbss
    ] # mmc_read_data
    for i in tsts:

# Path: fiddle/staticanalysis.py
# class LongWriteInfo():
#     def __init__(self, elf, start, end, thumb):
#         r2.run_aab(elf) # run basic block analysis
#         self.valid = True
#         self.start_ins = None
#         self.start_ins_addr = None
#         self.write_ins = None
#         self.write_ins_addr = None
#         self.finish_ins = None
#         self.finish_ins_addr = None
#         self.start = start
#         self.end = end
#         self.elf = elf
#         self.thumb = thumb
#         self.valid = False
#         self.branch_ins_addr = None
#         self.branch_ins = None
#         # grab basic blocks surrounding this region
#         r2.gets(elf, "s 0x%x" % self.start)
#         if self.thumb:  # force r2 to use the correct instruction size. sigh.
#             r2.gets(elf, "ahb 16")
#             r2.gets(elf, "e asm.bits=16")
#         else:
#             r2.gets(elf, "ahb 32")
#             r2.gets(elf, "e asm.bits=32")
#         self.bbs = r2.get(elf, "pdbj")
#         next = self.bbs[-1]["offset"] + self.bbs[-1]["size"]
#         while next < end:
#             r2.get(elf, "s 0x%x" % next)
#             self.bbs.extend(r2.get(elf, "pdbj"))
#             next = self.bbs[-1]["offset"] + self.bbs[-1]["size"]
#         # grab one more basic block
#         r2.get(elf, "s 0x%x" % next)
#         self.bbs.extend(r2.get(elf, "pdbj"))
# 
#     def calculate_info(self):
#         # lookup write instruction
#         nwrites = 0
#         elf = self.elf
#         for i in self.bbs:
#             mne = i["opcode"].split()[0]
#             if InstructionAnalyzer._is_mne_memstore(mne):
#                 nwrites += 1
#                 if (self.start <= i["offset"]) and (i["offset"] <= self.end):
#                     if self.write_ins is not None:
#                         # if there are two write instruction in basic block, don't know what to do
#                         self.valid = False
#                         break
#                     else:
#                         self.write_ins = i
#                         self.valid = True
#                         self.write_ins_addr = self.write_ins["offset"]
#         if nwrites > 1:
#             print "Warning: %s write ins in these blocks" % nwrites
# 
#         if not self.valid:
#             return
# 
#         # look for branch after write to find loop
#         branch = None
#         unconditional = False
#         for b in self.bbs:
#             if b["offset"] < self.write_ins_addr:
#                 continue
#             if b["type"] == u"cjmp" or b["type"] == u"jmp":
#                 if b["type"] == "jmp":
#                     dst = b["jump"]
#                     r2.gets(elf, "s 0x%x" % dst)
#                     for next in r2.get(elf, "pdbj"):
#                         if next["type"] == u"cjmp" or next["type"] == "jmp":
#                             if next["type"] == "cjmp":
#                                 jump = next["jump"]
#                                 if jump not in [ii["offset"] for ii in self.bbs]:
#                                     self.finish_ins_addr = jump
#                                 else:
#                                     self.finish_ins_addr = next["offset"] + next["size"]
#                             else:
#                                 # don't handle this case yet
#                                 self.valid = False
#                             break
#                     break
#                     #branch = r2.get(elf, "pdj 1")[0]
#                     #self.finish_ins_addr = branch["offset"] + branch["size"]
#                 else:
#                     branch = b
#                     jump = branch["jump"]
#                     if jump not in [ii["offset"] for ii in self.bbs]:
#                         self.finish_ins_addr = jump
#                     else:
#                         self.finish_ins_addr = branch["offset"] + branch["size"]
# 
#         r2.gets(elf, "s 0x%x" % self.finish_ins_addr)
#         self.finish_ins = r2.get(elf, "pdj 1")[0]
#         self.start_ins_addr = self.write_ins_addr
#         self.start_ins = self.write_ins
# 
#     def __repr__(self):
#         if not self.valid:
#             return "<invalid longwrite @ 0x%x>" % self.start_ins_addr
#         else:
#             return "<longwrite [start=0x%x,write=0x%x,done=0x%x]>" % (self.start_ins_addr, self.write_ins_addr, self.finish_ins_addr)


# Path: fiddle_extra/find_write_loops.py
import fiddle.staticanalysis
import fiddle.r2_keeper as r2
import sys
from fiddle.staticanalysis import LongWriteInfo

            return "<invalid longwrite @ 0x%x>" % self.start_ins_addr
        else:
            return "<longwrite [start=0x%x,write=0x%x,done=0x%x]>" % (self.start_ins_addr, self.write_ins_addr, self.finish_ins_addr)

#    def __repr__(self):
#        return str(self)

def longwrite_info(elf, addr, thumb):
    l = LongWriteInfo(elf, start, end, thumb)
    return l

def analyze(elf):
    r2.get(elf, "aas")
    tsts = [(0x40208b6e, True),
             (0x402025c0, False), # bss
             (0x40208b24, True), # memset
            # (0x40208b30, True), # memset, just 8 bits at most
             (0x40208b50, True), # memcpy
            (0x40206de0, True)] # mmc_read_data

    #for i in tsts:
    #    l = longwrite_info(elf, i[0], i[1])
    #    print l

    tsts = [(0x40208b1e, 0x40208b20, True), # memset
            (0x40208b50, 0x40208b54, True), # memcpy
            (0x40206dd6, 0x40206dde, True), # mmc_read_data
            (0x402025c4, 0x402025c8, False) # clearbss
    ] # mmc_read_data
    for i in tsts:

        l = LongWriteInfo(elf, *i)