//--------------------------------------------------------------------------
static void declare_class(ea_t ea, const char *entryname)
{
  static const char class_name[] = "ClassStruct";
  struc_t *sptr = get_struc(get_struc_id(class_name));
  if ( sptr == NULL )
  {
    sptr = get_struc(add_struc(BADADDR, class_name));
    if ( sptr == NULL )
      return;
    opinfo_t mt;
    mt.ri.flags = REF_OFF32;
    mt.ri.target = BADADDR;
    mt.ri.base = 0;
    mt.ri.tdelta = 0;
    add_struc_member(sptr, "superClass",   BADADDR, offflag()|dwrdflag(), &mt,  4);
    add_struc_member(sptr, "masterOffset", BADADDR, wordflag(), NULL, 2);
    add_struc_member(sptr, "methodCount",  BADADDR, decflag()|wordflag(), NULL, 2);
    add_struc_member(sptr, "instanceSize", BADADDR, decflag()|wordflag(), NULL, 2);
    add_struc_member(sptr, "vdRelocTable", BADADDR, wordflag(), NULL, 2);
    add_struc_member(sptr, "relocTable",   BADADDR, wordflag(), NULL, 2);
    mt.ec.tid = get_class_struct_flags_enum();
    mt.ec.serial = 0;
    add_struc_member(sptr, "flags",        BADADDR, enumflag()|byteflag(), &mt, 1);
    add_struc_member(sptr, "masterMethods",BADADDR, byteflag(), NULL, 1);
  }
  asize_t size = get_struc_size(sptr);
  doStruct(ea, size, sptr->id);
  int count = get_word(ea+6);
//  bool c_handlers = get_byte(ea+14) & (1<<6);
  ea += size;
  ea_t messages = ea;
  doWord(ea, count*2);
  op_dec(ea, 0);
  ea += 2*count;
  doDwrd(ea, count*4);
  set_offset(ea, 0, 0);
  for ( int i=0; i < count; i++ )
  {
    ea_t idx = ea + 4*i;
    ea_t pea = toEA(get_word(idx+2), get_word(idx));
    auto_make_proc(pea);
    char name[MAXSTR];
    qsnprintf(name, sizeof(name), "%s_%u", entryname, get_word(messages+2*i));
    add_entry(pea, pea, name, true);
  }
// commented out because it doesn't work properly
// see geoplan.geo, entry number 1 for example
//  if ( c_handlers )
//    declare_parameter_types(ea+count*4, count);
}
Beispiel #2
0
static int notify(processor_t::idp_notify msgid, ...)   // Various messages
{
  va_list va;
  va_start(va, msgid);

// A well behaving processor module should call invoke_callbacks()
// in his notify() function. If this function returns 0, then
// the processor module should process the notification itself
// Otherwise the code should be returned to the caller:

  int code = invoke_callbacks(HT_IDP, msgid, va);
  if ( code ) return code;

  switch ( msgid )
  {
    case processor_t::newfile:
      {
// ig: вообще у меня теперь такая точка зрения:
//     не надо в коде задавать вид имен.
//     при желании это можно сделать в ida.cfg:
//      #ifdef __80196__
//        DUMMY_NAMES_TYPE = NM_SHORT
//      #endif

        segment_t *sptr = get_first_seg();
        if( sptr != NULL )    set_segm_class( sptr, "CODE" );

        ea_t ea, ea1;

        for( int i = 0; i < qnumber(entries); i++ )
        {
          ea = toEA( inf.baseaddr, entries[i].off );

          if( isEnabled(ea) )
          {
            switch( entries[i].type )
            {
              case I196F_BTS:
                doByte( ea, entries[i+1].off-entries[i].off );
                set_cmt( ea, entries[i].cmt, 0 );
                break;

              case I196F_CMT:
                if( entries[i].cmt )
                  add_long_cmt( ea, 1, "%s", entries[i].cmt );
                else
                  describe( ea, 1, "" );
                break;

              case I196F_OFF:
                doWord( ea, 2 );
                set_offset( ea, 0, toEA( inf.baseaddr, 0 ) );

                ea1 = toEA( inf.baseaddr, get_word( ea ) );
                auto_make_proc( ea1 );
//dash: long_cmt здесь не смотрится, так как рисуется до заголовка
//      хорошо бы поставить func_cmt, но к этому моменту функций еще нет
//      как быть?
//ig: воспользоваться простым комментарием
//    при создании функции комментарий перетащится
                set_cmt( ea1, entries[i].cmt, 1 );
            }

            set_name( ea, entries[i].name );
          }
        }

        ea = toEA( inf.baseaddr, 0x2080 );
        if( isEnabled( ea ) )
        {
          inf.beginEA = ea;
          inf.startIP = 0x2080;
        }

        segment_t s;
        s.startEA = toEA( inf.baseaddr, 0 );
        s.endEA   = toEA( inf.baseaddr, 0x400 );
        s.sel     = inf.baseaddr;
        s.type    = SEG_IMEM;                         // internal memory
// ig: лучше искать дырку не от нуля, а от базы загрузки
//      ea_t bottom = toEA( inf.baseaddr, 0 );
//      intmem    = s.startEA = freechunk( bottom, 1024, 0xF );
//      s.endEA   = s.startEA + 1024;
//      s.sel     = ushort(s.startEA >> 4);
// dash: дырку искать не пришлось, но я оставил это как пример на будущее
        add_segm_ex( &s, "INTMEM", NULL, ADDSEG_OR_DIE);

        predefined_t *ptr;
        for( ptr = iregs; ptr->name != NULL; ptr++ )
        {
          ea_t ea = toEA( inf.baseaddr, ptr->addr );
          ea_t oldea = get_name_ea( BADADDR, ptr->name );
          if( oldea != ea )
          {
            if( oldea != BADADDR )    set_name( oldea, NULL );
            do_unknown( ea, DOUNK_EXPAND );
            set_name( ea, ptr->name );
          }
          if( ptr->cmt != NULL )      set_cmt( ea, ptr->cmt, 1 );
        }
      }
//      do16bit( 0x18, 2 );           // SP always word
      break;

    case processor_t::oldfile:
      for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->startEA) )
      {
        if ( getSRarea(s->startEA) == NULL )
        {
          segreg_t sr;
          sr.startEA = s->startEA;
          sr.endEA   = s->endEA;
          sr.reg(WSR)  = 0;
          sr.reg(WSR1) = 0;
          sr.reg(rVds) = inf.baseaddr;
          sr.settags(SR_autostart);
          SRareas.create_area(&sr);
        }
      }
      break;

    case processor_t::newseg:
                      // default DS is equal to Base Address
      (va_arg(va, segment_t *))->defsr[rVds-ph.regFirstSreg] = inf.baseaddr;
      break;

    case processor_t::newprc:
      extended = va_arg(va,int) != 0;
      if ( !extended )
        ph.flag &= ~PR_SEGS;
      else
        ph.flag |= PR_SEGS;
    default:
      break;
  }
  va_end(va);

  return(1);
}
Beispiel #3
0
//----------------------------------------------------------------------
// New method: symbol enumeration callback
//lint -e{818} could be declared as pointing to const
static BOOL CALLBACK EnumerateSymbolsProc(
        PSYMBOL_INFO psym,
        ULONG /*SymbolSize*/,
        PVOID delta)
{
  symbols_found++;
  ea_t ea = (ea_t)(psym->Address + *(adiff_t*)delta);
  const char *name = psym->Name;

  int maybe_func = 0; // maybe
  switch ( psym->Tag )
  {
    case SymTagFunction:
    case SymTagThunk:
#ifndef PDBTOTIL
      auto_make_proc(ea); // certainly a func
#endif
      maybe_func = 1;
      break;
    case SymTagNull:
    case SymTagExe:
    case SymTagCompiland:
    case SymTagCompilandDetails:
    case SymTagCompilandEnv:
    case SymTagData:
    case SymTagAnnotation:
    case SymTagUDT:
    case SymTagEnum:
    case SymTagFunctionType:
    case SymTagPointerType:
    case SymTagArrayType:
    case SymTagBaseType:
    case SymTagTypedef:
    case SymTagBaseClass:
    case SymTagFunctionArgType:
    case SymTagUsingNamespace:
    case SymTagVTableShape:
    case SymTagVTable:
    case SymTagCustom:
    case SymTagCustomType:
    case SymTagManagedType:
    case SymTagDimension:
      maybe_func = -1;
      break;
    case SymTagBlock:
    case SymTagLabel:
    case SymTagFuncDebugStart:
    case SymTagFuncDebugEnd:
      maybe_func = 2;
      break;
    case SymTagPublicSymbol:
    case SymTagFriend:
    default:
      break;
  }

  bool ok = apply_name(ea, name, maybe_func);
  // New dbghelp.dll/symsrv.dll files return names without the terminating zero.
  // So, as soon as we have a long name, shorter names will have garbage at the end.
  // Clean up the name to avoid problems.
  size_t len = strlen(name);
  memset((void*)name, '\0', len);
  return ok;
}
Beispiel #4
0
static int notify(processor_t::idp_notify msgid, ...) { // Various messages:
  va_list va;
  va_start(va, msgid);

// A well behaving processor module should call invoke_callbacks()
// in his notify() function. If this function returns 0, then
// the processor module should process the notification itself
// Otherwise the code should be returned to the caller:

  int code = invoke_callbacks(HT_IDP, msgid, va);
  if ( code ) return code;


  switch(msgid)
  {
    case processor_t::init:
      inf.mf = 1;                                 // MSB first
    default:
      break;

    case processor_t::newfile:
      {

        segment_t *sptr = get_first_seg();
        if( sptr != NULL )
        {
          if( sptr->startEA - get_segm_base( sptr ) == 0 )
          {
            inf.beginEA = sptr->startEA + 0xC;
            inf.startIP = 0xC;

            for( int i = 0; i < qnumber(entries); i++ )
            {
              ea_t ea = sptr->startEA + entries[i].off;
              if( isEnabled(ea) )
              {
                doWord( ea, 2 );
// ig: set_op_type - внутренняя функция, ее нельзя использовать
//                set_op_type( ea, offflag(), 0 );
                set_offset( ea, 0, sptr->startEA );
                ea_t ea1 = sptr->startEA + get_word( ea );
                auto_make_proc( ea1 );
                set_name( ea, entries[i].name );
// ig: так получше будет?
                set_cmt( sptr->startEA+get_word(ea), entries[i].cmt, 1 );
              }
            }
          }

          set_segm_class( sptr, "CODE" );
        }

        segment_t s;
        ea_t bottom = toEA( inf.baseaddr, 0 );
        intmem       = s.startEA = freechunk( bottom, 256, 0xF );
        s.endEA      = s.startEA + 256;
        s.sel        = allocate_selector( s.startEA >> 4 );
        s.type       = SEG_IMEM;                    // internal memory
        add_segm_ex( &s, "INTMEM", NULL, ADDSEG_OR_DIE);

        const predefined_t *ptr;
        for( ptr = iregs; ptr->name != NULL; ptr++ )
        {
          ea_t ea = intmem + ptr->addr;
          ea_t oldea = get_name_ea( BADADDR, ptr->name );
          if( oldea != ea )
          {
            if( oldea != BADADDR )    set_name( oldea, NULL );
            do_unknown( ea, DOUNK_EXPAND );
            set_name( ea, ptr->name );
          }
          if( ptr->cmt != NULL )      set_cmt( ea, ptr->cmt, 1 );
        }
      }
      break;

    case processor_t::oldfile:
      sel_t sel;
      if( atos( "INTMEM", &sel) ) intmem = specialSeg(sel);
      break;

    case processor_t::newseg:
      {                 // default DS is equal to CS
        segment_t *sptr = va_arg(va, segment_t *);
        sptr->defsr[rVds-ph.regFirstSreg] = sptr->sel;
      }
  }
  va_end(va);

  return(1);
}