Beispiel #1
0
//----------------------------------------------------------------------
static void fixup(uint32 ea, uint32 delta, int extdef)
{
  fixup_data_t fd;
  fd.type = FIXUP_OFF32;
  if ( extdef ) fd.type |= FIXUP_EXTDEF;
  segment_t *s = getseg(delta);
  fd.displacement = get_long(ea);
  if ( s == NULL ) {
    fd.sel = 0;
    fd.off = delta;
  } else {
    fd.sel = (ushort)s->sel;
    fd.off = delta - get_segm_base(s);
  }
  set_fixup(ea, &fd);
  uint32 target = get_long(ea) + delta;
  put_long(ea, target);
  set_offset(ea, 0, 0);
  cmd.ea = ea; ua_add_dref(0, target, dr_O); cmd.ea = BADADDR;
  if ( target != toc_ea
    && !has_name(get_flags_novalue(ea))
    && has_name(get_flags_novalue(target)) )
  {
    char buf[MAXSTR];
    if ( get_true_name(BADADDR, target, &buf[3], sizeof(buf)-3) != NULL )
    {
      buf[0] = 'T';
      buf[1] = 'C';
      buf[2] = '_';
      do_name_anyway(ea, buf);
      make_name_auto(ea);
    }
  }
//  toc.charset(ea,XMC_TC+1,1);
}
Beispiel #2
0
ea_t GetDelayedBranchAdr(void)   // if previous instruction is delayed jump return jump adr, else -1
{
  int16 disp;

  if (! isFlow(uFlag)) return BADADDR; // Does the previous instruction exist and pass execution flow to the current byte?

  if (cmd.size <= 0) return BADADDR;

  int sub = 3; // backward offset to skip 3 previous 1-word instruction

  ea_t ea = cmd.ea - sub;

  if (isCode(get_flags_novalue(ea)))	  // Does flag denote start of an instruction?
  {
    int code = get_full_byte(ea); // get the instruction word

    if ((code & 0xff000000) == 0x61000000) // Branch unconditionally (delayed)
        return code & 0xffffff;

    if ((code & 0xffe00000) == 0x6a200000) // BranchD conditionally
    {
        disp = code & 0xffff;
        return  cmd.ea + disp;
    }

    if ((code & 0xfe200000) == 0x6e200000) // DecrementD and branch conditionally
    {
        disp = code & 0xffff;
        return  cmd.ea + disp;
    }
  }


  return BADADDR;
}
Beispiel #3
0
//--------------------------------------------------------------------------
void idaapi cr16c_data(ea_t ea) 
{
   char obuf[256];
   init_output_buffer(obuf, sizeof(obuf));
   int col = 0;
   uint32 flags = get_flags_novalue(ea);
   if (isWord(flags)) {
      out_snprintf("%s %xh", ash.a_word ? ash.a_word : "", get_word(ea));
   }
   else if (isDwrd(flags)) {
      out_snprintf("%s %xh", ash.a_dword ? ash.a_dword : "", get_long(ea));
   }
   else { //if (isByte(flags)) {
      int val = get_byte(ea);
      char ch = ' ';
      if (val >= 0x20 && val <= 0x7E) {
         ch = val;
      }
      out_snprintf("%s %02xh   ; %c", ash.a_byte ? ash.a_byte : "", val, ch);
   }
   term_output_buffer();
   gl_comm = 1;
   MakeLine(obuf);
   return;
}
Beispiel #4
0
//----------------------------------------------------------------------
static void destroy_if_unnamed_array(ea_t ea)
{
    flags_t F = get_flags_novalue(ea);
    if ( isTail(F) && segtype(ea) == SEG_IMEM )
    {
        ea_t head = prev_not_tail(ea);
        if ( !has_user_name(get_flags_novalue(head)) )
        {
            do_unknown(head, DOUNK_SIMPLE);
            doByte(head, ea-head);
            ea_t end = nextthat(ea, inf.maxEA, f_isHead, NULL);
            if ( end == BADADDR ) end = getseg(ea)->endEA;
            doByte(ea+1, end-ea-1);
        }
    }
}
Beispiel #5
0
bool idaapi create_func_frame(func_t *pfn) {
    if ( pfn == NULL )
        return 0;

    ea_t ea = pfn->startEA;
    insn_t insn[4];
    int i;

    for (i = 0; i < 4; i++) {
        decode_insn(ea);
        insn[i] = cmd;
        ea += cmd.size;
    }

    i = 0;
    ushort regsize = 0;            // number of saved registers

    // first insn is not either push fp OR st fp, @-sp
    if ( (insn[i].itype != m32r_push || insn[i].Op1.reg != rFP ) &&
        (insn[i].itype != m32r_st || insn[i].Op1.reg != rFP || insn[i].Op2.reg != rSP || insn[i].Op2.specflag1 != fRIAS))
    {
        return 0;
    }

    regsize += 4;
    i++;

    // next insn is push lr OR st lr, @-sp
    if ( (insn[i].itype == m32r_push && insn[i].Op1.reg == rLR ) ||
        (insn[i].itype == m32r_st && insn[i].Op1.reg == rFP && insn[i].Op2.reg == rLR && insn[i].Op2.specflag1 != fRIAS))
    {
        regsize += 4;
        i++;
    }

    // next insn is not addi sp, #imm
    if ( insn[i].itype != m32r_addi || insn[i].Op1.reg != rSP )
        return 0;

    sval_t offset = - (sval_t) insn[i].Op2.value;

    // toggle to the negative sign of the immediate operand of the addi insn
    if ( !is_invsign(insn[i].ea, get_flags_novalue(insn[i].ea), 2) )
      toggle_sign(insn[i].ea, 2);

    i++;

    // next insn is not mv fp, sp
    if ( insn[i].itype != m32r_mv || insn[i].Op1.reg != rFP || insn[i].Op2.reg != rSP )
        return 0;

#if DEBUG
    msg("=> %d bytes\n", - (signed) insn[1].Op2.value);
#endif

    pfn->flags |= (FUNC_FRAME | FUNC_BOTTOMBP);
    //setflag((uint32 &) pfn->flags, FUNC_FRAME | FUNC_BOTTOMBP, 1);
    return add_frame(pfn, offset, regsize, 0);
}
Beispiel #6
0
//----------------------------------------------------------------------
static void TouchArg(op_t &x, int isload)
{
  switch ( x.type )
  {
    case o_displ:
    case o_imm:
      if ( op_adds_xrefs(uFlag, x.n) )
      {
        int outf = x.type != o_imm ? OOF_ADDR : 0;
        ua_add_off_drefs2(x, dr_O, outf|OOF_SIGNED);
      }
      break;

    case o_mem:
    case o_ind_mem:
    case o_reg:
    case o_ind_reg:
      {
        ea_t dea;
        if ( x.type == o_mem || x.type == o_ind_mem )
        {
          dea = map_addr(x.addr, x.n, true);
        }
        else
        {
          if ( x.reg >= rRR0 )
            dea = map_addr(x.reg - rRR0, x.n, true);
          else
            dea = map_addr(x.reg - rR0, x.n, true);
        }
        ua_dodata2(x.offb, dea, x.dtyp);
        if ( !isload )
          doVar(dea);
        ua_add_dref(x.offb, dea, isload ? dr_R : dr_W);
        if ( !has_user_name(get_flags_novalue(dea)) && dea > intmem)
        {
          char buf[10];
          int num = dea - intmem;
          if ( num < 0x100 )
          {
            qsnprintf(buf, sizeof(buf), "R%d", num);
          }
          else if ( num < 0x1000 )
          {
            qsnprintf(buf, sizeof(buf), "ERF_%X_%d", num >> 8, num & 0xFF);
          }
          else
          {
            int reg_no     = ((num >> 4) & 0xF0) + (num & 0xF);
            int subbank_no = ((num >> 4) & 0xF) + 1;
            qsnprintf(buf, sizeof(buf), "R%d_%X", reg_no, subbank_no);
          }
          set_name(dea, buf, SN_NOWARN);
        }
Beispiel #7
0
//----------------------------------------------------------------------
static int canFlow(void)
{
  if ( isC2() ) return 1;
  if ( !isFlow(uFlag) ) return 1;               // no previous instructions
  ea_t ea = prevInstruction(cmd.ea);
  if ( cmd.size == 2 )                          // our instruction is long
  {
    ; // nothing to do
  }
  else
  {                                             // our instruction short
    if ( (cmd.ea-ea) == 2 )                     // prev instruction long
      return 1;                                 // can flow always
    flags_t F = get_flags_novalue(ea);
    if ( !isCode(F) || !isFlow(F) ) return 1;   // no prev instr...
    ea = prevInstruction(ea);
  }
  flags_t F = get_flags_novalue(ea);
  return !isCode(F) || !isDelayedStop((ushort)get_full_byte(ea));
}
//---------------------------------------------------------------------------
static void idaapi ch_enter(void *obj, uint32 n)
{
  x86seh_ctx_t *ctx = (x86seh_ctx_t *)obj;
  if ( --n < ctx->handlers.size() )
  {
    ea_t ea = ctx->handlers[n];
    if ( !isCode(get_flags_novalue(ea)) )
      create_insn(ea);

    jumpto(ea);
  }
}
Beispiel #9
0
//----------------------------------------------------------------------
ea_t find_first_insn_in_packet(ea_t ea)
{
  while ( (ea & 0x1F) != 0 )
  {
    ea_t ea2 = prev_not_tail(ea);
    if ( ea2 == BADADDR
      || !isCode(get_flags_novalue(ea2))
      || (get_long(ea2) & BIT0) == 0 ) break;
    ea = ea2;
  }
  return ea;
}
Beispiel #10
0
//----------------------------------------------------------------------
static bool canFlow(void)
{
  if ( ! isFlow(uFlag) ) return 1;             // no previous instructions
  ea_t ea = cmd.ea - 4;
  flags_t F = get_flags_novalue(ea);
  if ( isFlow(F) && isCode(F) )
  {
    if ( isDelayedStop(get_long(ea)) )         // now or later
    {
      ea -= 4;
      if ( !isCode(get_flags_novalue(ea)) || !isDual(get_long(ea)) ) return 0;
      return 1;
    }
    if ( isFlow(F) )
    {
      ea -= 4;
      return !isCode(get_flags_novalue(ea)) || !isDelayedStop(get_long(ea));
    }
  }
  return 1;
}
Beispiel #11
0
// check and create a flat 32 bit jump table -- the most common case
static void check_and_create_flat32(
        jump_table_type_t /*jtt*/,
        switch_info_ex_t &si)
{
  // check the table contents
  ea_t table = si.jumps;
  segment_t *s = getseg(table);
  if ( s == NULL )
    return;
  size_t maxsize = size_t(s->endEA - table);
  int size = si.ncases;
  if ( size > maxsize )
    size = (int)maxsize;

  int i;
  insn_t saved = cmd;
  for ( i=0; i < size; i++ )
  {
    ea_t ea = table + 4*i;
    flags_t F = getFlags(ea);
    if ( !hasValue(F) )
      break;
    if ( i && (has_any_name(F) || hasRef(F)) )
      break;
    ea_t target = segm_adjust_ea(getseg(table), si.elbase + get_long(ea));
    if ( !isLoaded(target) )
      break;
    flags_t F2 = get_flags_novalue(target);
    if ( isTail(F2) || isData(F2) )
      break;
    if ( !isCode(F2) && !decode_insn(target) )
      break;
  }
  cmd = saved;
  size = i;
  // create the table
  for ( i=0; i < size; i++ )
  {
    ea_t ea = table + 4*i;
    doDwrd(ea, 4);
    op_offset(ea, 0, REF_OFF32, BADADDR, si.elbase);
    ea_t target = si.elbase + segm_adjust_diff(getseg(table), get_long(ea));
    ua_add_cref(0, target, fl_JN);
  }
  si.flags  |= SWI_J32;
  if ( si.defjump != BADADDR )
    si.flags |= SWI_DEFAULT;
  si.ncases  = (uint16)size;
  si.startea = cmd.ea;
  set_switch_info_ex(cmd.ea, &si);
}
Beispiel #12
0
bool delayed_stop(void)
{
  if (! isFlow(uFlag)) return false;

  if (cmd.size <= 0 || cmd.size > 2) return false;

  int sub = 2 - cmd.size; // backward offset to skip the previous 1-word instruction in the case of 2 consecutive 1-word instructions

  // first, we analyze 1-word instructions
  ea_t ea = cmd.ea - sub - 1;
  if (isCode(get_flags_novalue(ea)))
  {
    int code = get_full_byte(ea); // get the instruction word
    switch (code)
    {
      case 0xF6E2: // TMS320C54_baccd,   // Branch to Location Specified by Accumulator       1111 01ZS 1110 0010                      BACC[D] src
      case 0xF7E2:
      case 0xF6E6: // TMS320C54_fbaccd,  // Far Branch to Location Specified by Accumulator   1111 01ZS 1110 0110                      FBACC[D] src
      case 0xF7E6:
      case 0xF6E4: // TMS320C54_fretd,   // Far Return                                        1111 01Z0 1110 0100                      FRET[D]
      case 0xF6E5: // TMS320C54_freted,  // Enable Interrupts and Far Return From Interrupt   1111 01Z0 1110 0101                      FRETE[D]
      case 0xFE00: // TMS320C54_retd,    // Return                                            1111 11Z0 0000 0000                      RET[D]
      case 0xF6EB: // TMS320C54_reted,   // Enable Interrupts and Return From Interrupt       1111 01Z0 1110 1011                      RETE[D]
      case 0xF69B: // TMS320C54_retfd,   // Enable Interrupts and Fast Return From Interrupt  1111 01Z0 1001 1011                      RETF[D]
        return true;
    }
  }
  // else, we analyze 2-word instructions
  ea = cmd.ea - sub - 2;
  if (isCode(get_flags_novalue(ea)))
  {
    int code = get_full_byte(ea); // get the first instruction word
    if ( code == 0xF273             // TMS320C54_bd,      // Branch Unconditionally      1111 00Z0 0111 0011 16-bit constant      B[D] pmad
      || (code & 0xFF80) == 0xFA80) // TMS320C54_fbd,     // Far Branch Unconditionally  1111 10Z0 1 7bit constant=pmad(22-16) 16-bit constant=pmad(15-0)  FB[D] extpmad
        return true;
  }
  return false;
}
Beispiel #13
0
void run(int)
{
  netnode n("$ vmm functions");
  ea_t ea = get_screen_ea();    // get current address
  if ( !isCode(get_flags_novalue(ea)) ) return; // not an instruction
  ea_t callee = n.altval(ea)-1;         // get the callee address from the database
  char buf[MAXSTR];
  qsnprintf(buf, sizeof(buf), form, help);
  if ( AskUsingForm_c(buf, &callee) )
  {
    n.altset(ea, callee+1);     // save the new address
    noUsed(ea);                 // reanalyze the current instruction
  }
}
Beispiel #14
0
//----------------------------------------------------------------------
int find_ar(ea_t *res)
{
  ea_t ea = cmd.ea;
  for ( int i=0; i < lookback; i++ )
  {
    ea = prevInstruction(ea);
    if ( !isCode(get_flags_novalue(ea)) ) break;
    ushort code = (ushort)get_full_byte(ea);
    if ( isC2() )
    {
      switch ( code >> 11 )
      {
        case 6:                 // LAR
          return 0;
        case 0x18:              // LARK
          *res = toEA(dataSeg(),(code & 0xFF));
          return 1;
        case 0x1A:              // LRLK
          if ( (code & 0xF8FF) == 0xD000 )
          {
            ushort b = (ushort)get_full_byte(ea+1);
            *res = toEA(dataSeg(), b);
            return 1;
          }
      }
      continue;
    }
    switch ( code >> 11 )
    {
      case 0:                   // Load AR from addressed data
        return 0;               // LAR found, unknown address
      case 0x16:                // Load AR short immediate
        *res = toEA(dataSeg(), code & 0xFF);
        return 1;
      case 0x17:                // Load AR long immediate
        if ( (code & ~7) == 0xBF08 )
        {
          ushort b = (ushort)get_full_byte(ea+1);
          *res = toEA(dataSeg(),b);
          return 1;
        }
    }
  }
  return 0;
}
Beispiel #15
0
//---------------------------------------------------------------------------
// Validate table attributes
static bool check_table(ea_t table, uval_t elsize, uval_t tsize)
{
  flags_t F;
  if ( getseg(table) == NULL || isCode((F=get_flags_novalue(table))) || isTail(F) )
  {
    warning("AUTOHIDE NONE\nIncorrect table address %a", table);
    return false;
  }
  if ( elsize != 1 && elsize != 2 && elsize != 4 && elsize != 8 )
  {
    warning("AUTOHIDE NONE\nIncorrect table element size %d", elsize);
    return false;
  }
  flags_t DF = get_flags_by_size((size_t)elsize);
  if ( !can_define_item(table, elsize*tsize, DF) )
  {
    warning("AUTOHIDE NONE\nCan not create table at %a size %d", table, tsize);
    return false;
  }
  return true;
}
Beispiel #16
0
//----------------------------------------------------------------------
static void setup_far_func(func_t *pfn)
{
  if ( (pfn->flags & FUNC_FAR) == 0 )
  {
    ea_t ea1 = pfn->startEA;
    ea_t ea2 = pfn->endEA;
    while ( ea1 < ea2 )
    {
      if ( isCode(get_flags_novalue(ea1)) )
      {
        decode_insn(ea1);
        if ( is_far_ending() )
        {
          pfn->flags |= FUNC_FAR;
          update_func(pfn);
          break;
        }
      }
      ea1 = next_head(ea1, ea2);
    }
  }
}
Beispiel #17
0
//----------------------------------------------------------------------
static bool may_be_skipped(void)
{
  ea_t ea = cmd.ea - 1;
  if ( isCode(get_flags_novalue(ea)) )
  {
    int code = get_full_byte(ea);
    switch ( code & 0xFC00 )
    {
// 0001 00rd dddd rrrr     cpse    rd, rr  4  Compare, Skip if Equal
      case 0x1000:
// 1111 110r rrrr xbbb     sbrc    rr, b      Skip if Bit in I/O Register Cleared
// 1111 111r rrrr xbbb     sbrs    rr, b      Skip if Bit in I/O Register Set
      case 0xFC00:
        return true;
// 1001 1001 pppp pbbb     sbic    p, b       Skip if Bit in Register Cleared
// 1001 1011 pppp pbbb     sbis    p, b       Skip if Bit in Register Set
      case 0x9800:
        return (code & 0x0100) != 0;
    }
  }
  return false;
}
Beispiel #18
0
void idaapi run(int)
{
  static const char * nname;
  if ( ph.id == PLFM_MIPS )
    nname = "$ mips";
  else if ( ph.id == PLFM_ARM )
    nname = " $arm";
  else
    nname = "$ vmm functions";
  netnode n(nname);
  ea_t ea = get_screen_ea();    // get current address
  if ( !isCode(get_flags_novalue(ea)) ) return; // not an instruction
  ea_t callee = n.altval(ea)-1;         // get the callee address from the database
  // remove thumb bit for arm
  if ( ph.id == PLFM_ARM )
    callee &= ~1;
  char buf[MAXSTR];
  qsnprintf(buf, sizeof(buf), form, help);
  if ( AskUsingForm_c(buf, &callee) )
  {
    if ( callee == BADADDR )
    {
      n.altdel(ea);
    }
    else
    {
      if ( ph.id == PLFM_ARM && (callee & 1) == 0 )
      {
        // if we're calling a thumb function, set bit 0
        sel_t tbit = getSR(callee, T);
        if ( tbit != 0 && tbit != BADSEL )
          callee |= 1;
      }
      n.altset(ea, callee+1);     // save the new address
    }
    noUsed(ea);                 // reanalyze the current instruction
  }
}
Beispiel #19
0
bool delayed_stop(void)
{
  if (! isFlow(uFlag)) return false;	// Does the previous instruction exist and pass execution flow to the current byte?

  if (cmd.size <= 0) return false;

  int sub = 3; // backward offset to skip 3 previous 1-word instruction

  ea_t ea = cmd.ea - sub;

  if (isCode(get_flags_novalue(ea)))		// Does flag denote start of an instruction?
  {
    int code = get_full_byte(ea); // get the instruction word

	if ((code & 0xff000000) == 0x61000000)	return true;	// Branch unconditionally delayed				0110 0001 xxxx xxxx xxxx xxxx xxxx xxxx
	if ((code & 0xfdff0000) == 0x68200000)	return true;	// Branch conditionally delayed (with U cond)			0110 10x0 001x xxxx xxxx xxxx xxxx xxxx
	//if ((code & 0xfc3f0000) == 0x6c200000)	return true;	// Decrement and branch conditionally (with U cond)	0110 11xx xx1x xxxx xxxx xxxx xxxx xxxx
	// выброшено, т.к. используется в основном для огранизации циклов
	// а циклы не покидают пределы процедуры
  }


  return false;
}
Beispiel #20
0
//----------------------------------------------------------------------
bool is_basic_block_end(void)
{
  if (delayed_stop()) return true;
  return ! isFlow(get_flags_novalue(cmd.ea+cmd.size));
}
Beispiel #21
0
//----------------------------------------------------------------------
bool jump_pattern_t::follow_tree(ea_t ea, int n)
{
  if ( n == 0 )
    return true;
  int rsaved[sizeof(r)];
  bool ssaved[sizeof(spoiled)];
  memcpy(rsaved, r, sizeof(r));
  memcpy(ssaved, spoiled, sizeof(spoiled));
  bool success = false;
  if ( n < 0 )
  {
    success = true;
    n = -n;
  }
  jmsg("follow_tree(%a, %d)\n", ea, n);
  if ( !skip[n] )
  {
    if ( eas[n] == BADADDR )
    {
      cmd.ea = ea;
      bool found_insn = false;
      while ( true )
      {
        if ( cmd.ea < minea )
          break;
        farref = false;
        ea_t prev = BADADDR;
        if ( allow_noflows || isFlow(get_flags_novalue(cmd.ea)) )
          prev = decode_prev_insn(cmd.ea);
        if ( prev == BADADDR )
        {
          if ( !allow_farrefs )
            break;
          ea_t cur_addr = cmd.ea;
          if ( decode_preceding_insn(cmd.ea, &farref) == BADADDR )
            break;
          
          // skip branches which are used to glue blocks together
          if ( farref && is_branch_to(cur_addr) )
            continue;
        }

        if ( handle_mov() )
          continue;
        if ( (this->*check[n])() )
        {
          found_insn = true;
          break;
        }
        if ( failed )
          return false;
        jmsg("%a: can't be %d.", cmd.ea, n);
        jmsg(" rA=%d%s rB=%d%s rC=%d%s rD=%d%s rE=%d%s\n",
                        r[1], spoiled[1] ? "*" : "",
                        r[2], spoiled[2] ? "*" : "",
                        r[3], spoiled[3] ? "*" : "",
                        r[4], spoiled[4] ? "*" : "",
                        r[5], spoiled[5] ? "*" : "");
        check_spoiled();
      }
      if ( !found_insn )
      {
        memcpy(r, rsaved, sizeof(r));
        if ( success )
          goto SUCC;
        return false;
      }
      eas[n] = cmd.ea;
    }
    if ( eas[n] >= ea )
    {
      jmsg("%a: depends on %a\n", ea, eas[n]);
      return success;
    }
    ea = eas[n];
    jmsg("%a: found %d\n", cmd.ea, n);
  }
SUCC:
  if ( depends[n][0] && !follow_tree(ea, depends[n][0]) )
    return success;
  if ( depends[n][1] && !follow_tree(ea, depends[n][1]) )
    return success;
  jmsg("follow_tree(%d) - ok\n", n);
  memcpy(spoiled, ssaved, sizeof(spoiled));
  return true;
}
Beispiel #22
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;
}
Beispiel #23
0
bool has_meaningful_name(ea_t ea) {
	_ASSERTE(isEnabled(ea));
	char tmp[MAXNAMESIZE];
	return has_name(get_flags_novalue(ea)) && get_true_name(BADADDR, ea, CPY(tmp)) != 0
		&& !pcre_match("^unknown_libname_\\d+$", tmp);
}
Beispiel #24
0
//----------------------------------------------------------------------
static void TouchArg(op_t &x,int isAlt,int isload) {

  switch ( x.type ) {

    case o_phrase:
           //Добавляем в список ошибок(выводим сообщение)
           //ошибку и адресс где это случилось
           //QueueMark(Q_jumps, cmd.ea);
    case o_void:
    case o_reg:

      break;


    case o_sr:
    case o_displ:
       //Установить для данного байта признак immedia
      doImmd(cmd.ea);
      //Получить флаг для указанного линейного адресса
      if ( !isAlt ) {
        uint32 offb;
        ushort addr = ushort(x.addr);
        if ( x.type == o_displ  ) {
          addr += (ushort)cmd.ip;
          addr += cmd.size;
          //Получить линейный адресс
          offb = (uint32)toEA(codeSeg(addr,x.n), 0);
          DataSet(x, offb+addr, isload);
        } else if ( isOff(uFlag, x.n) ) {
reref:
          ua_add_off_drefs2(x, dr_O, x.type == o_displ ? OOF_ADDR : 0);
          if ( x.type == o_displ )
            //Преобразовать данные по указанному линейному адрессу в указанный тип
            ua_dodata2(x.offb, calc_target(cmd.ea+x.offb, cmd.ea, x.n, x.addr), x.dtyp);
        } else if ( x.type == o_displ && !x.reg && !isDefArg(uFlag, x.n ) &&
                 set_offset(cmd.ea, x.n, toEA(cmd.cs,0))) goto reref;
      }
      break;

   case o_stk:
   case o_imm:
       {
         //Установить для данного байта признак immedia
         doImmd(cmd.ea);
         if ( isOff(get_flags_novalue(cmd.ea), x.n) )
           ua_add_off_drefs2(x, dr_O, 0);
       }
       break;


   case o_ab:
       {
            if ( x.TypeOper == TAB_INDIRECTED_ABS_X )
            {
               ea_t ea = toEA(cmd.cs, x.addr);
               ua_dodata2(x.offb, ea, dt_word);
               //добавить крос референсы для текущей инструкции
               ua_add_dref(x.offb, ea, isload ? dr_R : dr_W);

               //получить данные
               uint32 Addr;
               Addr = get_word(ea);
               Addr = uint32( Addr | (getPG<<16));
               //добавить крос референсы для текущей инструкции
               ua_add_cref(2, Addr, fl_JF);
             }
            else
               DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload);
       }
       break;

   case o_mem:
   {
       // Конвертирование в данные(указан адресс) по указанному типу,
       //добавить крос референсы для текущей инструкции
     switch ( x.TypeOper )
     {
       case TDIR_DIR_Y:
       case TDIR_DIR_X:
       case TDIR_DIR:
       case TDIR_INDIRECT_DIR:
       case TDIR_INDIRECT_DIR_X:
       case TDIR_INDIRECT_DIR_Y:
       case TDIR_L_INDIRECT_DIR:
       case TDIR_L_INDIRECT_DIR_Y:
        {
          if ( getDPReg == 1 )
          {
             uint32 d = x.addr & 0xC;
             x.addr &= 0xFF3F;
             DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload);
             x.addr |=d;
          }
          else
             DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload);

        }
        break;

       default:
          DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload);

      }//end switch
   }
      break;


    case o_near:
      {
        //Получить линейный адресс
        ea_t ea = toEA(cmd.cs, x.addr);

        switch ( cmd.itype )
        {

           case m7900_jsr:
                {
                   //добавить крос референсы для текущей инструкции
                   ua_add_cref(x.offb, ea, fl_CN );
                   if ( !func_does_return(ea) )
                      flow = false;
                }
               break;

           case m7900_jsrl:
                 //добавить крос референсы для текущей инструкции
                 ua_add_cref(x.offb, ea, fl_CF);
                 if ( !func_does_return(ea) )
                   flow = false;
               break;

           case m7900_jmpl:
                 //добавить крос референсы для текущей инструкции
                 ua_add_cref(x.offb, ea, fl_JF);
               break;


            default:
                   ua_add_cref(x.offb, ea, fl_JN);
                break;
        }
      }
      break;

    default:
//      warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type);
      break;
  }
}
Beispiel #25
0
// Process function
void processFunction(func_t *f)
{
	// Skip tiny functions
	if(f->size() >= 5)
	{
		// Don't add comments to API wrappers
        char name[MAXNAMELEN]; name[0] = name[SIZESTR(name)] = 0;
		if(!apiMap.empty())
		{
			if(get_short_name(BADADDR, f->startEA, name, SIZESTR(name)))
			{
				if(apiMap.find(name) != apiMap.end())
					return;
			}
		}

		// Iterate function body
        STRLIST importLstTmp;
        LPSTR commentPtr = NULL;
		char comment[MAXSTR]; comment[0] = comment[SIZESTR(comment)] = 0;
        UINT commentLen = 0;

        #define ADDNM(_str) { UINT l = strlen(_str); memcpy(comment + commentLen, _str, l); commentLen += l; _ASSERT(commentLen < MAXSTR); }

        func_item_iterator_t it(f);
		do
		{
            ea_t currentEA = it.current();

			// Will be a "to" xref
			xrefblk_t xb;
			if(xb.first_from(currentEA, XREF_FAR))
			{
				BOOL isImpFunc = FALSE;
                name[0] = 0;

				// If in import segment
				// ============================================================================================
				ea_t refAdrEa = xb.to;
				if(isInImportSeg(refAdrEa))
				{
					flags_t flags = get_flags_novalue(refAdrEa);
					if(has_name(flags) && hasRef(flags) && isDwrd(flags))
					{
						if(get_short_name(BADADDR, refAdrEa, name, SIZESTR(name)))
						{
							// Nix the imp prefix if there is one
							if(strncmp(name, "__imp_", SIZESTR("__imp_")) == 0)
								memmove(name, name + SIZESTR("__imp_"), ((strlen(name) - SIZESTR("__imp_")) + 1));

							isImpFunc = TRUE;
						}
						else
							msg(EAFORMAT" *** Failed to get import name! ***\n", refAdrEa);
					}
				}
				// Else, check for import wrapper
				// ============================================================================================
				else
				if(!apiMap.empty())
				{
					// Reference is a function entry?
					flags_t flags = get_flags_novalue(refAdrEa);
					if(isCode(flags) && has_name(flags) && hasRef(flags))
					{
						if(func_t *refFuncPtr = get_func(refAdrEa))
						{
							if(refFuncPtr->startEA == refAdrEa)
							{
								if(get_short_name(BADADDR, refAdrEa, name, SIZESTR(name)))
								{
									// Skip common unwanted types "sub_.." or "unknown_libname_.."
									if(
										// not "sub_..
										/*"sub_"*/ (*((PUINT) name) != 0x5F627573) &&

										// not "unknown_libname_..
										/*"unknown_"*/ ((*((PUINT64) name) != 0x5F6E776F6E6B6E75) && (*((PUINT64) (name + 8)) != /*"libname_"*/ 0x5F656D616E62696C)) &&

										// not nullsub_..
										/*"nullsub_"*/ (*((PUINT64) name) != 0x5F6275736C6C756E)
										)
									{
										// Nix the import prefixes
										if(strncmp(name, "__imp_", SIZESTR("__imp_")) == 0)
											memmove(name, name + SIZESTR("__imp_"), ((strlen(name) - SIZESTR("__imp_")) + 1));

										// Assumed to be a wrapped import if it's in the list
										isImpFunc = (apiMap.find(name) != apiMap.end());
									}
								}
								else
									msg(EAFORMAT" *** Failed to get function name! ***\n", refAdrEa);
							}
						}
					}
				}

				// Found import function to add list
				if(isImpFunc)
				{
					// Skip those large common STL names
					if(strncmp(name, "std::", SIZESTR("std::")) != 0)
					{
						// Skip if already seen in this function
						BOOL known = FALSE;
						for(STRLIST::iterator ji = importLstTmp.begin(); ji != importLstTmp.end(); ji++)
						{
							if(strcmp(ji->c_str(), name) == 0)
							{
								known = TRUE;
								break;
							}
						}

						// Not seen
						if(!known)
						{
							importLstTmp.push_front(name);

                            // Append to existing comments w/line feed
                            if(!commentLen && !commentPtr)
                            {
                                commentPtr = get_func_cmt(f, true);
                                if(!commentPtr)
                                    get_func_cmt(f, false);

                                if(commentPtr)
                                {
                                    commentLen = strlen(commentPtr);
                                    // Bail out not enough comment space
                                    if(commentLen >= (MAXSTR - 20))
                                    {
                                        qfree(commentPtr);
                                        return;
                                    }

                                    memcpy(comment, commentPtr, commentLen);
                                    ADDNM("\n"MYTAG);
                                }
                            }

                            if(!commentLen)
                                ADDNM(MYTAG);

							// Append a "..." (continuation) and bail out if name hits max comment length
							if((commentLen + strlen(name) + SIZESTR("()") + sizeof(", ")) >= (MAXSTR - sizeof("...")))
							{
                                ADDNM(" ...");
								break;
							}
							// Append this function name
							else
							{
								if(importLstTmp.size() != 1)
                                    ADDNM(", ");
                                ADDNM(name); ADDNM("()");
							}
						}
					}
					else
					{
						//msg("%s\n", szName);
					}
				}
			}

		}while(it.next_addr());

		if(!importLstTmp.empty() && commentLen)
		{
            // Add comment
            comment[commentLen] = 0;
			set_func_cmt(f, comment, true);
			commentCount++;
		}

        if(commentPtr)
            qfree(commentPtr);
	}
}
static void op_emu(op_t& x, int fIsLoad)
{
    char szLabel[128];
    cref_t ftype;
    ea_t ea;

    switch (x.type)
    {
    case o_reg:
    case o_phrase:
        return;
    case o_imm:
        if (!fIsLoad) break;
        op_imm(cmd.ea);
        return;
    case o_displ:
    case o_mem:
        switch (cmd.itype)
        {
        case M8B_IORD:
        case M8B_IOWR:
        case M8B_IOWX:
        case M8B_IPRET:
            ea = toIOP(x.addr);
            if (ea != BADADDR)
            {
                ua_dodata2(x.offb, ea, x.dtyp);
                if (!fIsLoad) doVar(ea);
                ua_add_dref(x.offb, ea, cmd.itype == M8B_IORD ? dr_R : dr_W);
            }
            break;
        default:
            ea = toRAM(x.addr);
            if (ea != BADADDR)
            {
                if (!has_any_name(get_flags_novalue(ea)))
                {
                    qsnprintf(szLabel, sizeof(szLabel), "ram_%0.2X", x.addr);
                    set_name(ea, szLabel, SN_NOWARN);
                }
                ua_dodata2(x.offb, ea, x.dtyp);
                if (!fIsLoad) doVar(ea);
                ua_add_dref(x.offb, ea, cmd.itype == M8B_IORD ? dr_R : dr_W);
            }
        }
        return;
    case o_near:
        ea = toROM(x.addr);
        if (ea != BADADDR)
        {
            switch (cmd.itype)
            {
            case M8B_INDEX:
                if (!has_any_name(get_flags_novalue(ea)))
                {
                    qsnprintf(szLabel, sizeof(szLabel), "tbl_%0.4X", x.addr);
                    set_name(ea, szLabel, SN_NOWARN);
                }
                ua_add_dref(x.offb, ea, dr_R);
                break;
            default:
                ftype = fl_JN;
                if (InstrIsSet(cmd.itype, CF_CALL))
                {
                    if (!func_does_return(ea))
                        fFlow = false;
                    ftype = fl_CN;
                }
                ua_add_cref(x.offb, ea, ftype);
            }
        }
        return;
    }

    warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type);
}
Beispiel #27
0
static bool check_for_table_jump(void)
{
  ea_t base = BADADDR, table = BADADDR, defea = BADADDR;
  int size = 0, elsize = 0;

  int i;
  bool ok = false;
  insn_t saved = cmd;
  for ( i=0; !ok && i < qnumber(patterns); i++ )
  {
    ok = patterns[i](&base, &table, &defea, &size, &elsize);
    cmd = saved;
  }
  if ( !ok ) return false;

  if ( table != BADADDR ) table = toEA(cmd.cs, table);
  if ( base  != BADADDR ) base  = toEA(cmd.cs, base);
  if ( defea != BADADDR ) defea = toEA(cmd.cs, defea);

  // check the table contents
  int oldsize = size;
  segment_t *s = getseg(table);
  if ( s == NULL ) return false;
  int maxsize = int(s->endEA - table);
  if ( size > maxsize ) size = maxsize;

  for ( i=0; i < size; i++ )
  {
    ea_t ea = table+i*elsize;
    flags_t F = getFlags(ea);
    if ( !hasValue(F)
      || (i && (has_any_name(F) || hasRef(F))) ) break;
    int el = elsize == 1 ? get_byte(ea) : get_word(ea);
    flags_t F2 = get_flags_novalue(base+el);
    if ( isTail(F2)
      || isData(F2)
      || (!isCode(F2) && !decode_insn(base+el)) ) break;
  }
  cmd = saved;
  size = i;
  if ( size != oldsize )
    msg("Warning: jpt_%04a calculated size of %d forced to %d!\n",
                                      cmd.ip, oldsize, size);

  // create the table
  if ( size == 0 ) return false;
  for ( i=0; i < size; i++ )
  {
    ea_t ea = table + i*elsize;
    (elsize == 1 ? doByte : doWord)(ea, elsize);
    op_offset(ea, 0, elsize == 1 ? REF_OFF8 : REF_OFF16, BADADDR, base);
    ua_add_cref(0, base + (elsize==1?get_byte(ea):get_word(ea)), fl_JN);
  }
  char buf[MAXSTR];
  qsnprintf(buf, sizeof(buf), "def_%a", cmd.ip);
//  set_name(defea, buf, SN_NOWARN|SN_LOCAL);         // temporary kernel bug workaround
  set_name(defea, buf, SN_NOWARN);
  qsnprintf(buf, sizeof(buf), "jpt_%a", cmd.ip);
  set_name(table, buf, SN_NOWARN);
  return true;
}
Beispiel #28
0
//----------------------------------------------------------------------
static void TouchArg(op_t &x,int isload)
{
  ea_t ea;
  switch ( x.type )
  {
  case o_phrase:                // 2 registers or indirect addressing
    if ( cmd.itype != TMS_mar && cmd.itype != TMS2_mar
                && find_ar(&ea) ) goto set_dref;
  case o_reg:
  case o_bit:
  case o_cond:
    break;
  case o_imm:
    if ( ! isload ) goto badTouch;
    doImmdValue();
    if ( isOff(uFlag, x.n) )
      ua_add_off_drefs2(x, dr_O, is_mpy() ? OOF_SIGNED : 0);
    break;
  case o_mem:
    ea = toEA(dataSeg_op(x.n),x.addr);
set_dref:
    ua_dodata2(x.offb, ea, x.dtyp);
    if ( ! isload )
      doVar(ea);
    ua_add_dref(x.offb,ea,isload ? dr_R : dr_W);
    if ( x.type == o_mem )
      if ( cmd.itype == TMS_dmov  ||
           cmd.itype == TMS_ltd   ||
           cmd.itype == TMS_macd  ||
           cmd.itype == TMS_madd  ||
           cmd.itype == TMS2_dmov ||
           cmd.itype == TMS2_macd  ) ua_add_dref(x.offb,ea+1,dr_W);
    break;
  case o_near:
    {
      ea_t segbase = codeSeg(x.addr, x.n);
      ea = toEA(segbase, x.addr);
      if ( cmd.itype == TMS_blpd ||
           cmd.itype == TMS_mac  ||
           cmd.itype == TMS_macd ||
           cmd.itype == TMS2_blkp ||
           cmd.itype == TMS2_mac  ||
           cmd.itype == TMS2_macd
         ) goto set_dref;
      uval_t thisseg = cmd.cs;
      int iscall = InstrIsSet(cmd.itype,CF_CALL);
      if ( cmd.itype == TMS_rptb && isTail(get_flags_novalue(ea)) )
      {
        // small hack to display end_loop-1 instead of before_end_loop+1
        ea++;
      }

      ua_add_cref(x.offb,
                  ea,
                  iscall ? ((segbase == thisseg) ? fl_CN : fl_CF)
                         : ((segbase == thisseg) ? fl_JN : fl_JF));
      if ( iscall )
      {
        if ( !func_does_return(ea) )
          flow = false;
      }
    }
    break;
  default:
badTouch:
    warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type);
    break;
  }
}
Beispiel #29
0
//----------------------------------------------------------------------
static int LoadArg(op_t &x)
{
  dref_t xreftype;
  switch ( x.type ) {
  case o_reg:
    {
      if ( x.reg == R_sp ) goto Undefined;
//      AbstractRegister *in = &i5_getreg(x.reg);
//      if ( ! in->isDef() ) goto Undefined;
//      r.doInt(in->value());
      return 1;
    }
  case o_imm:
//    r.doInt(unsigned(x.value));
    xreftype = dr_O;
MakeImm:
    doImmdValue(x.n);
    if ( isOff(uFlag, x.n) )
      ua_add_off_drefs2(x, xreftype, 0);
    return 1;
  case o_displ:
//    r.undef();
    xreftype = dr_R;
    goto MakeImm;
  case o_mem:
    {
      ea_t ea = toEA(dataSeg_op(x.n),x.addr);
      ua_add_dref(x.offb,ea,dr_R);
      ua_dodata2(x.offb, ea, x.dtyp);
      if ( !isVar(get_flags_novalue(ea)) && isLoaded(ea) )
      {
//        r.doInt( x.dtyp != dt_byte ? get_word(ea) : char(get_byte(ea)) );
        return 1;
      }
    }
  case o_phrase:
Undefined:
//    r.undef();
    break;

  case o_near:
    {
      ea_t segbase = codeSeg(x.addr,x.n);
      ea_t ea = toEA(segbase,x.addr);
      ea_t thisseg = cmd.cs;
      int iscall = InstrIsSet(cmd.itype,CF_CALL);
      ua_add_cref(x.offb,
                  ea,
                  iscall ? ((segbase == thisseg) ? fl_CN : fl_CF)
                         : ((segbase == thisseg) ? fl_JN : fl_JF));
      if ( iscall && !func_does_return(ea) )
        flow = false;
//      r.doInt(unsigned(x.addr));
    }
    return 1;
  default:
//  warning("%a: %s,%d: bad load optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type);
    break;
  }
  return 0;
}
Beispiel #30
0
// Attempt to get information of and fix vftable at address
// Return TRUE along with info if valid vftable parsed at address
BOOL vftable::getTableInfo(ea_t ea, vtinfo &info)
{
    ZeroMemory(&info, sizeof(vtinfo));

	// Start of a vft should have an xref and a name (auto, or user, etc).
    // Ideal flags 32bit: FF_DWRD, FF_0OFF, FF_REF, FF_NAME, FF_DATA, FF_IVL
    //dumpFlags(ea);
    flags_t flags = get_flags_novalue(ea);
	if(hasRef(flags) && has_any_name(flags) && (isEa(flags) || isUnknown(flags)))
    {
        // Get raw (auto-generated mangled, or user named) vft name
        //if (!get_name(BADADDR, ea, info.name, SIZESTR(info.name)))
        //    msg(EAFORMAT" ** vftable::getTableInfo(): failed to get raw name!\n", ea);

        // Determine the vft's method count
        ea_t start = info.start = ea;
        while (TRUE)
        {
            // Should be an ea_t offset to a function here (could be unknown if dirty IDB)
            // Ideal flags for 32bit: FF_DWRD, FF_0OFF, FF_REF, FF_NAME, FF_DATA, FF_IVL
            //dumpFlags(ea);
            flags_t indexFlags = get_flags_novalue(ea);
            if (!(isEa(indexFlags) || isUnknown(indexFlags)))
            {
                //msg(" ******* 1\n");
                break;
            }

            // Look at what this (assumed vftable index) points too
            ea_t memberPtr = getEa(ea);
            if (!(memberPtr && (memberPtr != BADADDR)))
            {
                // vft's often have a zero ea_t (NULL pointer?) following, fix it
                if (memberPtr == 0)
                    fixEa(ea);

                //msg(" ******* 2\n");
                break;
            }

            // Should see code for a good vft method here, but it could be dirty
            flags_t flags = get_flags_novalue(memberPtr);
            if (!(isCode(flags) || isUnknown(flags)))
            {
                //msg(" ******* 3\n");
                break;
            }

            if (ea != start)
            {
                // If we see a ref after first index it's probably the beginning of the next vft or something else
                if (hasRef(indexFlags))
                {
                    //msg(" ******* 4\n");
                    break;
                }

                // If we see a COL here it must be the start of another vftable
                if (RTTI::_RTTICompleteObjectLocator::isValid(memberPtr))
                {
                    //msg(" ******* 5\n");
                    break;
                }
            }

            // As needed fix ea_t pointer, and, or, missing code and function def here
            fixEa(ea);
            fixFunction(memberPtr);

            ea += sizeof(ea_t);
        };

        // Reached the presumed end of it
        if ((info.methodCount = ((ea - start) / sizeof(ea_t))) > 0)
        {
            info.end = ea;
            //msg(" vftable: "EAFORMAT"-"EAFORMAT", methods: %d\n", rtInfo.eaStart, rtInfo.eaEnd, rtInfo.uMethods);
            return(TRUE);
        }
    }

    //dumpFlags(ea);
    return(FALSE);
}