Example #1
0
    def gen_function(self):
        ''' returns tuple of:
        1) list functions (we can have several functions in case we 
            need to levels of hashing)
        2) the operands lookup function (generates the key)        
        '''
        action_codegen = actions_codegen.actions_codegen_t(self.cvg.tuple2rule,
                                                       self.cvg.default_action,
                                                       self.cvg.strings_dict)
        self.cvg.action_codegen = action_codegen

        if self.cvg.no_constraints():
            fo = self._gen_empty_function(self.fname)
            return [fo], None
        
        phash = ild_phash.gen_hash(self.cvg)
        if phash == None:
            genutil.die("Failed to find perfect hash for %s" % self.fname)
        if verbosity.vfuncgen():
            self.cvg.log.write("%s" % phash)

        fos, operand_lu_fo = phash.gen_find_fos(self.fname)
        return fos, operand_lu_fo
Example #2
0
def gen_ph_fos(agi,
               cdict_by_map_opcode,
               log_fn,
               ptrn_dict,
               vv):
    """
    Returns a tuple (phash_lu, phash_fo_list, op_lu_list)
    * phash_lu:  is a traditional 2D dict by (map, opcode) to a
      hash function name.
    * phash_fo_list: is a list of all phash function objects created
      (we might have fos that are not in lookup table - when we have
      2-level hash functions).
    * op_lu_list:  is a list for all the operands lookup functions

    Also writes log file for debugging.
    """
    maps = ild_info.get_maps(agi)
    log_f = open(log_fn, 'w')
    cnames = set() # only for logging
    stats = {
             '0. #map-opcodes': 0,
             '1. #entries': 0,
             '2. #hentries': 0,
             '3. #hashes': 0,
             '4. #min_hashes': 0,
             '5. #cdict_size_1_to_10': 0,
             '6. #cdict_size_10_to_20': 0,
             '7. #cdict_size_20_to_100': 0,
             '8. #cdict_size_at_least_100': 0
             }
    lu_fo_list = []  
    op_lu_map = {} # fn name -> fn obj
    phash_lu = {}  # map, opcode -> fn name
    for insn_map in maps:
        phash_lu[insn_map] = {}
        zeros = 0
        for opcode in range(0, 256):
            opcode = hex(opcode)
            cdict = cdict_by_map_opcode[insn_map][opcode]
            if cdict:
                stats['0. #map-opcodes'] += 1
                stats['1. #entries'] += len(cdict.tuple2rule)
                cnames = cnames.union(set(cdict.cnames))
                _log(log_f,'XYZ VV: {} MAP:{} OPCODE:{}:\n{}\n'.format(
                    vv, insn_map, opcode, cdict))

                phash = ild_phash.gen_hash(cdict)
                if phash:
                    _log(log_f,"%s" % phash)
                    phash_id = 'map%s_opcode%s_vv%d' % (insn_map, opcode,
                                                        vv)
                    fname = "%s_%s" % (_find_fn_pfx,phash_id)
                    (fo_list, op_lu_fo) = phash.gen_find_fos(fname)
                    lu_fo_list.extend(fo_list)

                    #hold only one instance of each function
                    if op_lu_fo:
                        if op_lu_fo.function_name not in op_lu_map:
                            op_lu_map[op_lu_fo.function_name] = op_lu_fo
                    for fo in fo_list:
                        _log(log_f,'//find function:\n')
                        _log(log_f,fo.emit())
                        _log(log_f,'-----------------------------\n')
                    #FIXME: assumption: L2 function is last in the list
                    #maybe return dict or tuple to make a distinction between
                    #L2 and L1 functions?
                    phlu_fn = lu_fo_list[-1]
                    phash_lu[insn_map][opcode] = phlu_fn.function_name
                    phash.update_stats(stats)
                else:
                    _log(log_f,'---NOPHASH-----\n')
                    msg = "Failed to gen phash for map %s opcode %s"
                    ildutil.ild_err(msg % (insn_map, opcode))
            else:
                phash_lu[insn_map][opcode] = '(xed3_find_func_t)0'
                zeros = zeros + 1
        if zeros == 256: # all zero... shortcut to avoid scanning maps for "all-zeros"
            _log(log_f, "ZEROING phash_lu for map {} vv {}\n".format(insn_map, vv))
            phash_lu[insn_map] = None
    _log(log_f,"cnames: %s\n" %cnames)
    for key in sorted(stats.keys()):
        _log(log_f,"%s %s\n" % (key,stats[key]))
    log_f.close()
    return phash_lu, lu_fo_list, list(op_lu_map.values())