# Path: sibyl/learn/generator/generator.py
# class Generator(object):
#     '''
#     Abstract class used to represent a generator
#     A generator is a class that create a test from a snapshot
#     Here a test is a sibyl test init function and a sibyl test check function
#     '''
# 
#     def __init__(self, testcreator):
#         '''
#         @testcreator: TestCreator instance with associated information
#         '''
#         self.trace = testcreator.trace
#         self.prototype = testcreator.prototype
#         self.learnexceptiontext = testcreator.learnexceptiontext
#         self.types = testcreator.types
#         self.printer = Printer()
#         self.headerfile = testcreator.headerfile
#         self.ira = Machine(testcreator.machine).ira()
#         self.ptr_size = self.ira.sizeof_pointer()/8
#         self.logger = testcreator.logger
# 
#     def generate_test(self):
#         '''Abstract method that should return the string corresponding to the code of the init test'''
#         raise NotImplementedError("Abstract method")
# 
# Path: sibyl/learn/generator/templates.py

# 
# Path: sibyl/learn/trace.py
# class MemoryAccess(object):
#     '''Represent a memory block, read or write by the learned function'''
# 
#     def __init__(self, size, data, access):
# 
#         self.size = size
#         self.data = data
#         self.access = access
# 
#     def __str__(self):
#         str_access = ""
#         if self.access & PAGE_READ:
#             str_access += "READ"
#         if self.access & PAGE_WRITE:
#             if str_access != "":
#                 str_access += " "
#             str_access += "WRITE"
# 
#         return "size: " + str(self.size) + ", data: " + repr(self.data) + ", access: " + str_access
# 
#     def __repr__(self):
#         return "<" + str(self) + ">"
# 
# Path: sibyl/commons.py
# def objc_is_dereferenceable(target_type):
#     """Return True if target_type may be used as a pointer
#     @target_type: ObjC"""
#     return isinstance(target_type, (ObjCPtr, ObjCArray))


import struct
from sibyl.learn.generator.generator import Generator
from sibyl.learn.generator import templates as TPL
from sibyl.learn.trace import MemoryAccess
from miasm2.ir.ir import AssignBlock
from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE
from miasm2.expression.expression import *
from miasm2.expression.simplifications import expr_simp
from sibyl.commons import objc_is_dereferenceable
        self._add_arg(i, int(arg))
'''

checkResultTemplate = '''result = self._to_int(self._get_result())

expectedResult = {expectedResult}
if isinstance(expectedResult, tuple):
    expectedResult = expectedResult[0] + self.segBase{n}[expectedResult[1]]

ret = (result == expectedResult)
'''

# WARNING: any change to checkAllocWithoutRefTemplate have to be reported to checkAllocWithRefTemplate
checkAllocWithoutRefTemplate = '''
addrList = {addrList}

ret = ret and all([self._ensure_mem(offset + self.segBase{n}[segment], data) for ((offset, segment),data) in addrList])
'''

# WARNING: any change to checkAllocWithRefTemplate have to be reported to checkAllocWithoutRefTemplate
checkAllocWithRefTemplate = '''
addrList = {addrList}

refs = {refs}
ptrSize = self.abi.ira.sizeof_pointer()
for (offsetRef, segRef), ref in refs.iteritems():
    newData = self.pack(offsetRef + self.segBase{n}[segRef], ptrSize)
    for (writenOffset, writenSeg) in ref:
        for i, ((offsetA, segA), data) in enumerate(addrList):
            if segA == writenSeg and (offsetA <= writenOffset < offsetA + len(data)):

# Path: sibyl/learn/generator/generator.py
# class Generator(object):
#     '''
#     Abstract class used to represent a generator
#     A generator is a class that create a test from a snapshot
#     Here a test is a sibyl test init function and a sibyl test check function
#     '''
# 
#     def __init__(self, testcreator):
#         '''
#         @testcreator: TestCreator instance with associated information
#         '''
#         self.trace = testcreator.trace
#         self.prototype = testcreator.prototype
#         self.learnexceptiontext = testcreator.learnexceptiontext
#         self.types = testcreator.types
#         self.printer = Printer()
#         self.headerfile = testcreator.headerfile
#         self.ira = Machine(testcreator.machine).ira()
#         self.ptr_size = self.ira.sizeof_pointer()/8
#         self.logger = testcreator.logger
# 
#     def generate_test(self):
#         '''Abstract method that should return the string corresponding to the code of the init test'''
#         raise NotImplementedError("Abstract method")
# 
# Path: sibyl/learn/generator/templates.py

# 
# Path: sibyl/learn/trace.py
# class MemoryAccess(object):
#     '''Represent a memory block, read or write by the learned function'''
# 
#     def __init__(self, size, data, access):
# 
#         self.size = size
#         self.data = data
#         self.access = access
# 
#     def __str__(self):
#         str_access = ""
#         if self.access & PAGE_READ:
#             str_access += "READ"
#         if self.access & PAGE_WRITE:
#             if str_access != "":
#                 str_access += " "
#             str_access += "WRITE"
# 
#         return "size: " + str(self.size) + ", data: " + repr(self.data) + ", access: " + str_access
# 
#     def __repr__(self):
#         return "<" + str(self) + ">"
# 
# Path: sibyl/commons.py
# def objc_is_dereferenceable(target_type):
#     """Return True if target_type may be used as a pointer
#     @target_type: ObjC"""
#     return isinstance(target_type, (ObjCPtr, ObjCArray))


# Path: sibyl/learn/generator/pythongenerator.py
import struct
from sibyl.learn.generator.generator import Generator
from sibyl.learn.generator import templates as TPL
from sibyl.learn.trace import MemoryAccess
from miasm2.ir.ir import AssignBlock
from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE
from miasm2.expression.expression import *
from miasm2.expression.simplifications import expr_simp
from sibyl.commons import objc_is_dereferenceable

        self._add_arg(i, int(arg))
'''

checkResultTemplate = '''result = self._to_int(self._get_result())

expectedResult = {expectedResult}
if isinstance(expectedResult, tuple):
    expectedResult = expectedResult[0] + self.segBase{n}[expectedResult[1]]

ret = (result == expectedResult)
'''

# WARNING: any change to checkAllocWithoutRefTemplate have to be reported to checkAllocWithRefTemplate
checkAllocWithoutRefTemplate = '''
addrList = {addrList}

ret = ret and all([self._ensure_mem(offset + self.segBase{n}[segment], data) for ((offset, segment),data) in addrList])
'''

# WARNING: any change to checkAllocWithRefTemplate have to be reported to checkAllocWithoutRefTemplate
checkAllocWithRefTemplate = '''
addrList = {addrList}

refs = {refs}
ptrSize = self.abi.ira.sizeof_pointer()
for (offsetRef, segRef), ref in refs.iteritems():
    newData = self.pack(offsetRef + self.segBase{n}[segRef], ptrSize)
    for (writenOffset, writenSeg) in ref:
        for i, ((offsetA, segA), data) in enumerate(addrList):
            if segA == writenSeg and (offsetA <= writenOffset < offsetA + len(data)):

                data = data[0:writenOffset-offsetA] + newData + data[writenOffset-offsetA+ptrSize/8:]