class Couple(ICommand): """ Retrieve couples """ def __init__(self, log_file, log): super(Couple, self).__init__() self.__parser = BlockTraceParser(log_file) self.log = log def run(self): inp = dict() out = dict() SIZE_LIMIT = 10000 NROUND = 65536 self.log("parsing memory blocks...") for block in self.__parser.get(): if block.type != BlockTrace.ADDR: continue if block.io == BlockTrace.IN: if block.id not in inp.keys(): inp[block.id] = list() if len(inp[block.id]) < SIZE_LIMIT: inp[block.id].append(block.val) elif block.io == BlockTrace.OUT: if block.id not in out.keys(): out[block.id] = list() for i in xrange(NROUND): out[block.id].append(list()) out[block.id][block.val % NROUND].append(block.val) self.log("#f: {0} | #g: {1} | #in: {2} | #out: {3}".format( len(inp), len(out), reduce(lambda p, q: p + len(q), inp.values(), 0), reduce(lambda p, q: p + reduce(lambda x, y: x + len(y), q, 0), out.values(), 0), ), ) self.log("computing couples...") couples = list() for g, param_in in inp.items(): for f, param_out in out.items(): nb = 0 not_nb = 0 for param in param_in: if param in param_out[param % NROUND]: nb += 1 else: not_nb += 1 if float(not_nb) / float(len(param_in)) > 1 - 0.5: break rho = float(nb) / float(len(param_in)) if rho > 0.5: couples.append((f, g, rho)) for c in couples: print c return
class MemComb(ICommand): """ Retrieve allocators """ def __init__(self, mem_log_file, type_log_file, log): super(MemComb, self).__init__() self.__parser = BlockTraceParser(mem_log_file) self.__protos = TypeLogParser(type_log_file) self.log = log def __alloc(self): """ Try to retrieve the top-level allocator """ # return "libc.so.6:529408" # Number of new addresses outputted by each function nb_new_addr = dict() # Addresses seen so far addr_seen = AddrTable() # Call stack call_stack = CallStack() # For each block of data in the log file for block in self.__parser.get(): # IN PARAMETER if block.is_in(): call_stack.push(block) # OUT PARAMETER else: call_stack.expect(block.id, block.date) if block.is_addr(): if block.id not in nb_new_addr.keys(): nb_new_addr[block.id] = [0, 0] if not addr_seen.contains(block.val): nb_new_addr[block.id][0] += 1 addr_seen.add(block.val) nb_new_addr[block.id][1] += 1 call_stack.pop() return max(nb_new_addr.items(), key=lambda a: a[1][0])[0] def __wrappers(self, ALLOC): # Number of new addresses outputted by each function wrappers = dict() # Last output value last_addr = None # prev = None # TTL ttl = 0 # Call stack call_stack = CallStack() # For each block of data in the log file for block in self.__parser.get(): # IN PARAMETER if block.is_in(): call_stack.push(block) # OUT PARAMETER else: call_stack.expect(block.id, block.date) if block.is_addr(): if block.id in wrappers.keys(): wrappers[block.id][1] += 1 if block.id == ALLOC: last_addr = block.val depth = 1 prev = ALLOC elif last_addr is not None: if block.val == last_addr: if block.id not in wrappers.keys(): wrappers[block.id] = [0, 1, list(), list()] wrappers[block.id][0] += 1 wrappers[block.id][2].append(depth) wrappers[block.id][3].append(prev) depth += 1 prev = block.id # else: # last_addr = None # ttl = 0 # prev = None call_stack.pop() if call_stack.is_empty(): last_addr = None wrappers = map(lambda a: (a[0], float(a[1][0])/float(a[1][1]), mean(a[1][2]), max(set(a[1][3]), key=a[1][3].count)), sorted(wrappers.items(), key=lambda a: a[1][0])) wrappers = sorted(filter(lambda a: a[1] > 0.5, wrappers), key=lambda a:a[2]) WTREE = Wrapper(ALLOC, 1) for wrapper in wrappers: wrap = WTREE.get(wrapper[3], wrapper[2] - 1) if wrap is not None: wrap.add_child(Wrapper(wrapper[0], int(wrapper[1]))) else: print "Elaged: {0}".format(wrapper[0]) print WTREE.to_str(0) def __free(self, ALLOC): # return "__libc_free" # Number of new addresses outputted by each function nb_new_addr = dict() # Addresses seen so far addr_alloc = AddrTable(dic=True) # Call stack call_stack = CallStack() for block in self.__parser.get(): if not addr_alloc.contains(block.val): addr_alloc.add(block.val) if block.is_in() and block.id != ALLOC: addr_alloc.add_dic(block.val, block.id) elif block.is_out() and block.id == ALLOC: addr_alloc.add_dic(block.val, block.id) for adr, call in addr_alloc.items(): if len(call) == 0: continue if call[0] != ALLOC: continue while call.count(ALLOC) > 0: if call.index(ALLOC) == 0: call.pop(0) if len(call) > 0: free = call[-1] else: continue else: free = call[call.index(ALLOC) - 1] call = call[call.index(ALLOC)+1:] if free not in nb_new_addr.keys(): nb_new_addr[free] = 0 nb_new_addr[free] += 1 return max(nb_new_addr.items(), key=lambda a:a[1])[0] def compute_blocks(self, ALLOC, FREE): mem = Memory() size_stack = [(0, -1)] for block in self.__parser.get(): if block.id == ALLOC: if block.is_in() and block.is_num() and size_stack[-1][1] != block.date: size_stack.append((block.val, block.date)) elif block.is_out(): if len(size_stack) <= 1: raise Exception("ALLOC stack inconsistanc at date {0}".format(block.date)) size, date = size_stack.pop(-1) mem.alloc(block.val, size) elif block.id == FREE: if block.is_in(): mem.free(block.val) return def run(self, wrappers=True): ALLOC = self.__alloc() self.log("allocator found - {0}".format(ALLOC)) FREE = self.__free(ALLOC) self.log("liberator found - {0}".format(FREE)) self.log("checking consistancy of blocks...") self.compute_blocks(ALLOC, FREE) if wrappers: # Detecting suballocators SUBALLOC = self.__wrappers(ALLOC) return ALLOC, FREE
def __init__(self, log_file, log): super(Couple, self).__init__() self.__parser = BlockTraceParser(log_file) self.log = log
def __init__(self, mem_log_file, type_log_file, log): super(MemComb, self).__init__() self.__parser = BlockTraceParser(mem_log_file) self.__protos = TypeLogParser(type_log_file) self.log = log