/* #<pydoc> def create_switch_table(insn_ea, si): """ Create switch table from the switch information @param insn_ea: address of the 'indirect jump' instruction @param si: switch information @return: Boolean """ pass #</pydoc> */ idaman bool ida_export py_create_switch_table( ea_t insn_ea, PyObject *py_swi) { switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi); if ( swi == NULL ) return false; create_switch_table(insn_ea, swi); return true; }
//--------------------------------------------------------------------------- // The main function - called when the user selects the menu item static bool idaapi callback(void *) { // Calculate the default values to display in the form ea_t screen_ea = get_screen_ea(); segment_t *s = getseg(screen_ea); if ( s == NULL || !isCode(get_flags_novalue(screen_ea)) ) { warning("AUTOHIDE NONE\nThe cursor must be on the table jump instruction"); return false; } ea_t startea = screen_ea; while ( true ) { ea_t prev = prev_not_tail(startea); if ( !is_switch_insn(prev) ) break; startea = prev; } ea_t jumps = get_first_dref_from(screen_ea); uval_t jelsize = s->abytes(); uval_t jtsize = 0; if ( jumps != BADADDR ) { decode_insn(screen_ea); jtsize = guess_table_size(jumps); } uval_t shift = 0; uval_t elbase = 0; char input[MAXSTR]; input[0] = '\0'; ea_t defea = BADADDR; uval_t lowcase = 0; ushort jflags = 0; ushort vflags = 0; ea_t vtable = BADADDR; ea_t vtsize = 0; ea_t velsize = s->abytes(); reg_info_t ri; ri.size = 0; // If switch information is present in the database, use it for defaults switch_info_ex_t si; if ( get_switch_info_ex(screen_ea, &si, sizeof(si)) > 0 ) { jumps = si.jumps; jtsize = si.ncases; startea = si.startea; elbase = si.elbase; jelsize = si.get_jtable_element_size(); shift = si.get_shift(); defea = (si.flags & SWI_DEFAULT) ? si.defjump : BADADDR; if ( si.regnum != -1 ) get_reg_name(si.regnum, get_dtyp_size(si.regdtyp), input, sizeof(input)); if ( si.flags & SWI_SIGNED ) jflags |= 2; if ( si.flags2 & SWI2_SUBTRACT ) jflags |= 4; if ( si.flags & SWI_SPARSE ) { jflags |= 1; vtable = si.values; vtsize = jtsize; velsize = si.get_vtable_element_size(); if ( si.flags2 & SWI2_INDIRECT ) { vflags |= 1; jtsize = si.jcases; } if ( si.flags & SWI_JMP_INV ) vflags |= 2; } else { lowcase = si.lowcase; } } // Now display the form and let the user edit the attributes while ( AskUsingForm_c(main_form, &jumps, &jtsize, &jelsize, &shift, &elbase, &startea, input, &lowcase, &defea, &jflags) ) { if ( !check_table(jumps, jelsize, jtsize) ) continue; if ( shift > 3 ) { warning("AUTOHIDE NONE\nInvalid shift value (allowed values are 0..3)"); continue; } if ( !isCode(get_flags_novalue(startea)) ) { warning("AUTOHIDE NONE\nInvalid switch idiom start %a (must be an instruction", startea); continue; } ri.reg = -1; if ( input[0] != '\0' && !parse_reg_name(input, &ri) ) { warning("AUTOHIDE NONE\nUnknown input register: %s", input); continue; } if ( defea != BADADDR && !isCode(get_flags_novalue(defea)) ) { warning("AUTOHIDE NONE\nInvalid default jump %a (must be an instruction", defea); continue; } if ( jflags & 1 ) // value table is present { bool vok = false; while ( AskUsingForm_c(value_form, &vflags, &vtable, &vtsize, &velsize) ) { if ( (vflags & 1) == 0 ) vtsize = jtsize; if ( check_table(vtable, velsize, vtsize) ) { vok = true; break; } } if ( !vok ) break; } // ok, got and validated all params -- fill the structure si.flags = SWI_EXTENDED; si.flags2 = 0; if ( jflags & 2 ) si.flags |= SWI_SIGNED; if ( jflags & 4 ) si.flags2 |= SWI2_SUBTRACT; si.jumps = jumps; si.ncases = ushort(jtsize); si.startea = startea; si.elbase = elbase; if ( elbase != 0 ) si.flags |= SWI_ELBASE; si.set_jtable_element_size((int)jelsize); si.set_shift((int)shift); if ( defea != BADADDR ) { si.flags |= SWI_DEFAULT; si.defjump = defea; } if ( ri.reg != -1 ) si.set_expr(ri.reg, get_dtyp_by_size(ri.size)); if ( jflags & 1 ) // value table is present { si.flags |= SWI_SPARSE; si.values = vtable; si.set_vtable_element_size((int)velsize); if ( (vflags & 1) != 0 ) { si.flags2 |= SWI2_INDIRECT; si.jcases = (int)jtsize; si.ncases = (ushort)vtsize; } if ( (vflags & 2) != 0 ) si.flags |= SWI_JMP_INV; } else { si.lowcase = lowcase; } // ready, store it set_switch_info_ex(screen_ea, &si); create_switch_table(screen_ea, &si); setFlbits(screen_ea, FF_JUMP); create_insn(screen_ea); info("AUTOHIDE REGISTRY\nSwitch information has been stored"); break; } return true; }