Beispiel #1
0
/*
#<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;
}
Beispiel #2
0
//---------------------------------------------------------------------------
// 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;
}