def gen_modrm_lookup(united_lookup, debug): modrm_lookup = {} for insn_map in ild_info.get_dump_maps(): modrm_lookup[insn_map] = {} for opcode in range(0, 256): info_list = united_lookup.get_info_list(insn_map, hex(opcode)) info_list = ild_info.get_min_prio_list(info_list) if len(info_list) == 0: #no infos in map-opcode, illegal opcode has_modrm = _has_modrm_undef elif _is_modrm_conflict(info_list): #conflict in has_modrm value in map-opcode's info_list #try to resolve info = _resolve_modrm_conflict(info_list) if not info: ildutil.ild_err( 'UNRESOLVED CONFLICT IN MODRM\n infos:\n%s\n' % "\n".join([str(info) for info in info_list])) has_modrm = info.has_modrm else: #several infos that agree on has_modrm property, we can choose #any of them to get has_modrm info = info_list[0] has_modrm = info.has_modrm modrm_lookup[insn_map][hex(opcode)] = has_modrm return modrm_lookup
def gen_l1_functions_and_lookup(agi, instr_by_map_opcode, imm_dict): """Compute L1(conflict resolution) functions list and imm_bytes lookup tables dict. @param agi: all generators info @param instr_by_map_opcode: the 2D lookup by map-opcode to info objects list. instr_by_map_opcode['0x0']['0x78'] == [ild_info1, ild_info2, ... ] @type instr_by_map_opcode: {string(insn_map) : {string(opcode): [ild_info.ild_info_t]} } """ l1_resolution_fos = [] l1_lookup = {} for insn_map in ild_info.get_dump_maps_imm(agi): l1_lookup[insn_map] = {} for opcode in range(0, 256): #look in the hard-coded resolution functions #they are manually written for the two-immediates instructions if (insn_map, hex(opcode)) in _hardcoded_res_functions_imm: l1_fn = _hardcoded_res_functions_imm[(insn_map, hex(opcode))] l1_lookup[insn_map][hex(opcode)] = l1_fn continue info_list = instr_by_map_opcode.get_info_list( insn_map, hex(opcode)) #get only info objects with minimum priority info_list = ild_info.get_min_prio_list(info_list) is_conflict = _is_imm_conflict(info_list, imm_dict) if len(info_list) > 1 and is_conflict: l1_fo = _resolve_conflicts(agi, info_list, imm_dict) if not l1_fo: ildutil.ild_err( 'FAILED TO GENERATE L1 CONFLICT ' + 'RESOLUTION FUNCTION FOR IMM\n infos:\n %s' % "\n".join([str(info) for info in info_list])) l1_resolution_fos.append(l1_fo) l1_fn = l1_fo.function_name #if map-opcode pair is undefined the lookup function ptr is NULL #this will happen for opcodes like 0F in 0F map - totally illegal #opcodes, that should never be looked up in runtime. elif len(info_list) == 0: l1_fn = _imm0_fn else: #there are no conflicts, we can use L2 function as L1 info = info_list[0] l1_fn = get_l2_fn_from_info(info, imm_dict) if not l1_fn: return None l1_lookup[insn_map][hex(opcode)] = l1_fn return l1_resolution_fos, l1_lookup
def gen_getter_fn_lookup(agi, united_lookup, eosz_dict): # NOT USED """Compute L1(conflict resolution) functions list and eosz lookup tables dict. @param agi: all generators info @param united_lookup: the 2D lookup by map-opcode to info objects list. united_lookup['0x0']['0x78'] == [ild_info1, ild_info2, ... ] @type united_lookup: {string(insn_map) : {string(opcode): [ild_info.ild_info_t]} } """ l1_lookup = {} for insn_map in united_lookup.get_maps(): l1_lookup[insn_map] = {} for opcode in range(0, 256): info_list = united_lookup.get_info_list(insn_map, hex(opcode)) #get only info objects with minimum priority info_list = ild_info.get_min_prio_list(info_list) is_conflict = False if len(info_list) > 1: is_conflict = is_eosz_conflict(info_list) if is_conflict: genutil.msg("EOSZ CONFLICT MAP/OPCODE:{}/{}".format( insn_map, opcode)) # l1_fo = _resolve_conflicts(agi, info_list, nt_dict) # if not l1_fo: # ildutil.ild_err('FAILED TO GENERATE CONFLICT ' + # 'RESOLUTION FUNCTION FOR EOSZ\n infos:\n %s' % # "\n".join([str(info) for info in info_list])) # # l1_resolution_fos.append(l1_fo) # l1_fn = l1_fo.function_name l1_fn = None #if map-opcode pair is undefined the lookup function ptr is NULL #this will happen for opcodes like 0F in 0F map - totally illegal #opcodes, that should never be looked up in runtime. elif len(info_list) == 0: l1_fn = '(%s)0' % (ildutil.l1_ptr_typename) else: #there are no conflicts, we can use the eosz_nt_seq #function info = info_list[0] l1_fn = ild_nt.get_lufn(info.eosz_nt_seq, _eosz_token) l1_lookup[insn_map][hex(opcode)] = l1_fn return l1_lookup
def gen_getter_fn_lookup(agi, united_lookup, easz_dict): # NOT USED """Compute L1(conflict resolution) functions list and easz lookup tables dict. @param agi: all generators info @param united_lookup: the 2D lookup by map-opcode to info objects list. united_lookup['0x0']['0x78'] == [ild_info1, ild_info2, ... ] @type united_lookup: {string(insn_map) : {string(opcode): [ild_info.ild_info_t]} } """ l1_lookup = {} for insn_map in united_lookup.get_maps(): l1_lookup[insn_map] = {} for opcode in range(0, 256): info_list = united_lookup.get_info_list(insn_map, hex(opcode)) #get only info objects with minimum priority info_list = ild_info.get_min_prio_list(info_list) is_conflict = False if len(info_list) > 1: is_conflict = is_easz_conflict(info_list) if is_conflict: l1_fn = None #if map-opcode pair is undefined the lookup function ptr is NULL #this will happen for opcodes like 0F in 0F map - totally illegal #opcodes, that should never be looked up in runtime. elif len(info_list) == 0: l1_fn = '(%s)0' % (ildutil.l1_ptr_typename) else: #there are no conflicts, we can use the eosz_nt_seq #function info = info_list[0] l1_fn = ild_nt.get_lufn(info.easz_nt_seq, _easz_token) l1_lookup[insn_map][hex(opcode)] = l1_fn return l1_lookup
def gen_l1_functions_and_lookup(agi, united_lookup, disp_dict): """Compute L1(conflict resolution) functions list and disp_bytes lookup tables dict. @param agi: all generators info @param united_lookup: the 2D lookup by map-opcode to info objects list. united_lookup['0x0']['0x78'] == [ild_info1, ild_info2, ... ] @type united_lookup: {string(insn_map) : {string(opcode): [ild_info.ild_info_t]} } """ #list of L1 function objects that resolve conflicts in map-opcodes #functions. This list will be dumped to xed_ild_imm_l1.h l1_resolution_fos = [] #dictionary l1_lookup[insn_map][opcode] = l1_function_name #this dictionary will be used to dump the has_imm lookup tables l1_lookup = {} #dictionary from function body(as string) to list of function objects #with that body. #This dict will be used to bucket identical functions in order to #not define same functions more than once. l1_bucket_dict = collections.defaultdict(list) for insn_map in ild_info.get_maps(united_lookup.is_amd): l1_lookup[insn_map] = {} for opcode in range(0, 256): #look in the hardcoded resolution functions if (insn_map, hex(opcode)) in harcoded_res_functions: l1_fn = harcoded_res_functions[(insn_map, hex(opcode))] l1_lookup[insn_map][hex(opcode)] = l1_fn continue info_list = united_lookup.get_info_list(insn_map, hex(opcode)) #get only info objects with minimum priority info_list = ild_info.get_min_prio_list(info_list) is_conflict = _is_disp_conflict(info_list, disp_dict) if len(info_list) > 1 and is_conflict: l1_fo = _resolve_conflicts(agi, info_list, disp_dict) if not l1_fo: ildutil.ild_err( 'FAILED TO GENERATE L1 CONFLICT ' + 'RESOLUTION FUNCTION FOR DISP\n infos: %s' % "\n".join([str(info) for info in info_list])) l1_bucket_dict[l1_fo.emit_body()].append(l1_fo) l1_fn = l1_fo.function_name elif len(info_list) == 0: #if map-opcode pair is undefined the lookup function ptr is #NULL. #This will happen for opcodes like 0F in 0F map - totally #illegal opcodes, that should never be looked up in runtime. #We define NULL pointer for such map-opcodes l1_fn = '(%s)0' % (ildutil.l1_ptr_typename) else: #there are no conflicts, we can use L2 function as L1 info = info_list[0] l1_fn = get_l2_fn_from_info(info, disp_dict) l1_lookup[insn_map][hex(opcode)] = l1_fn #there are 18 L1 functions with same body (currently, may change #in future) #we are going to bucket L1 functions with identical body but different #names in order to have only one function for each unique body #FIXME: the bucketed function name is not self descriptive bucket_name = 'xed_lookup_function_DISP_BUCKET_%s_l1' cur_bucket = 0 for res_fun_list in list(l1_bucket_dict.values()): if len(res_fun_list) == 1: #only one such function - we should define it as is l1_resolution_fos.append(res_fun_list[0]) else: #more than one L1 function with identical body #we should define L1 function with that body #and fix references in the lookup table #the function name cur_buck_name = bucket_name % cur_bucket cur_bucket += 1 #fix references in the lookup table for res_fun in res_fun_list: for insn_map in list(l1_lookup.keys()): for opcode in list(l1_lookup[insn_map].keys()): cur_fn = l1_lookup[insn_map][opcode] if cur_fn == res_fun.function_name: l1_lookup[insn_map][opcode] = cur_buck_name #define the L1 function and add it to the list of L1 functions #to dump buck_fo = res_fun_list[0] buck_fo.function_name = cur_buck_name l1_resolution_fos.append(buck_fo) return l1_resolution_fos, l1_lookup