void search_objects(bool bForce) { if (!bScaned || bForce) { segment_t *text_seg = get_segm_by_name(".text"); if (text_seg != NULL) { ea_t ea_text = text_seg->startEA; while (ea_text <= text_seg->endEA) process_vtbl(ea_text); } segment_t *rdata_seg = get_segm_by_name(".rdata"); // support linux if (NULL == rdata_seg) rdata_seg = get_segm_by_name(".rodata"); if (rdata_seg != NULL) { ea_t ea_rdata = rdata_seg->startEA; while (ea_rdata <= rdata_seg->endEA) process_vtbl(ea_rdata); } process_rtti(); bScaned = true; } }
//-------------------------------------------------------------------------- //lint -esym(528,ioresp_ok) is not referenced static bool ioresp_ok(void) { if ( inf.like_binary() ) return true; else return get_segm_by_name("RAM") != NULL; }
bool VtableScanner::scan ( void ) { // Get .text and .rdata segments boundaries segment_t *textSeg = get_segm_by_name (".text"); segment_t *rdataSeg = get_segm_by_name (".rdata"); if (!textSeg || !rdataSeg) { msg ("Error : Cannot find the .text or .rdata segment."); return false; } ea_t rMin = rdataSeg->startEA, rMax = rdataSeg->endEA, cMin = textSeg->startEA, cMax = textSeg->endEA; if (rMin == 0) { rMin = cMin; rMax = cMax; } ea_t curAddress = rMin; ea_t curDword; while (curAddress < rMax) { curDword = get_long (curAddress); // Methods should reside in .text if (curDword >= cMin && curDword < cMax) { curAddress = this->checkVtable (curAddress); } else { curAddress += 4; } } msg ("Finished !\n"); msg ("Vtable count = %d", this->vtables.size()); return true; }
//Emulation heap constructor, indicate virtual address of base and max size //creates heap from existing IDA segment EmuHeap::EmuHeap(const char *name, unsigned int maxSize) { h = get_segm_by_name(name); head = NULL; base = h->startEA; size = h->endEA - base; max = maxSize + base; nextHeap = NULL; if (primaryHeap == NULL) { primaryHeap = this; } }
//-------------------------------------------------------------------------- static void setup_got(void) { netnode n("$ got"); if ( exist(n) ) got = n.altval(0) - 1; if ( got == BADADDR ) get_name_value(BADADDR, "_GLOBAL_OFFSET_TABLE_", &got); if ( got == BADADDR ) { segment_t *s = get_segm_by_name(".got"); if ( s != NULL ) got = s->startEA; } msg("DP is assumed to be %08a\n", got); }
QString IdaFrontend::architecture() { if (inf.procName == QLatin1String("ARM")) { return QLatin1String("arm-le"); } else if (inf.procName == QLatin1String("ARMB")) { return QLatin1String("arm-be"); } else { /* Assume x86 by default. */ if (segment_t *segment = get_segm_by_name(".text")) { switch (segment->bitness) { case 0: return QLatin1String("8086"); case 1: return QLatin1String("i386"); case 2: return QLatin1String("x86-64"); } } return QLatin1String("i386"); } }
//------------------------------------------------------------------ static bool apply_config_file(int _respect_info) { if ( strcmp(device, NONEPROC) == 0 ) // processor not selected return true; char cfgfile[QMAXFILE]; char cfgpath[QMAXPATH]; get_cfg_filename(cfgfile, sizeof(cfgfile)); if ( getsysfile(cfgpath, sizeof(cfgpath), cfgfile, CFG_SUBDIR) == NULL ) { #ifndef SILENT warning("ICON ERROR\n" "Can not open %s, I/O port definitions are not loaded", cfgfile); #endif return false; } deviceparams[0] = '\0'; if ( !CHECK_IORESP ) _respect_info = 0; respect_info = _respect_info; free_ioports(ports, numports); ports = read_ioports(&numports, cfgpath, device, sizeof(device), callback); if ( respect_info & IORESP_PORT ) { for ( int i=0; i < numports; i++ ) { ioport_t *p = ports + i; #ifdef I8051 segment_t *s = get_segm_by_name("FSR"); if ( s != NULL ) { set_name(p->address + s->startEA - 0x80, p->name); set_cmt(p->address + s->startEA - 0x80, p->cmt, true); } #else set_name(p->address, p->name); set_cmt(p->address, p->cmt, true); #endif } } return true; }
QString IdaFrontend::architecture() { reg_info_t regsize; if (inf.procName == QLatin1String("ARM")) { return QLatin1String(byteOrder() == ByteOrder::LittleEndian ? "arm-le" : "arm-be"); } else if (inf.procName == QLatin1String("ARMB")) { return QLatin1String("arm-be"); } else if (inf.procName == QLatin1String("psp")) { return QLatin1String("allegrex"); } else if (inf.procName == QLatin1String("mipsl")) { if(parse_reg_name("$zero", ®size)){ switch (regsize.size){ case 4: return QLatin1String("mips-le"); case 8: return QLatin1String("mips64-le"); } } else { return QLatin1String("mips-le"); } } else if (inf.procName == QLatin1String("mipsb")) { if(parse_reg_name("$zero", ®size)){ switch (regsize.size){ case 4: return QLatin1String("mips-be"); case 8: return QLatin1String("mips64-be"); } } else { return QLatin1String("mips-be"); } } else { /* Assume x86 by default. */ if (segment_t *segment = get_segm_by_name(".text")) { switch (segment->bitness) { case 0: return QLatin1String("8086"); case 1: return QLatin1String("i386"); case 2: return QLatin1String("x86-64"); } } return QLatin1String("i386"); } }
QString IdaFrontend::architecture() { if (inf.procName == QLatin1String("ARM")) { return QLatin1String(byteOrder() == ByteOrder::LittleEndian ? "arm-le" : "arm-be"); } else if (inf.procName == QLatin1String("ARMB")) { return QLatin1String("arm-be"); } else if (inf.procName == QLatin1String("PPC")) { return QLatin1String("ppc-be"); } else if (inf.procName == QLatin1String("PPCL")) { return QLatin1String("ppc-le"); } else if (inf.procName == QLatin1String("spu")) { return QLatin1String("spu-be"); } else { /* Assume x86 by default. */ if (segment_t *segment = get_segm_by_name(".text")) { switch (segment->bitness) { case 0: return QLatin1String("8086"); case 1: return QLatin1String("i386"); case 2: return QLatin1String("x86-64"); } } return QLatin1String("i386"); } }
/* * this is where we finally load the file and create segments and other processing */ void idaapi load_file(linput_t *li, ushort neflags, const char *fileformatname) { /* reset file position to 0 - accept_file changed it? */ qlseek(li, 0); /* add header structures */ add_types(); create_filename_cmt(); /* process header and create its own segment */ EFI_IMAGE_TE_HEADER teHeader = {0}; if (qlread(li, &teHeader, sizeof(EFI_IMAGE_TE_HEADER)) != sizeof(EFI_IMAGE_TE_HEADER)) { warning("Failed to read TE header\n"); return; } /* read the data to the database */ /* header starts at 0 */ ea_t delta = teHeader.StrippedSize - sizeof(EFI_IMAGE_TE_HEADER); ea_t header_start = teHeader.ImageBase - delta; /* header total size is the TE header plus all sections that follow */ ea_t header_end = teHeader.ImageBase - delta + sizeof(EFI_IMAGE_TE_HEADER) + teHeader.NumberOfSections * sizeof(EFI_IMAGE_SECTION_HEADER); #if 1 msg("Header start: 0x%llx\n", header_start); msg("Header end: 0x%llx\n", header_end); msg("Delta: 0x%llx\n", delta); #endif file2base(li, 0, header_start, header_end, 1); /* create the HEADER segment */ add_segm(0, header_start, header_end, "HEADER", "DATA"); /* set header structures */ doStruct(teHeader.ImageBase - delta, sizeof(EFI_IMAGE_TE_HEADER), efi_image_te_header_struct); for (uint8_t i = 0; i < teHeader.NumberOfSections; i++) { doStruct(teHeader.ImageBase - delta + sizeof(EFI_IMAGE_TE_HEADER) + i * sizeof(EFI_IMAGE_SECTION_HEADER), sizeof(EFI_IMAGE_SECTION_HEADER), efi_image_section_header_struct); } int headerPosition = sizeof(EFI_IMAGE_TE_HEADER); /* read sections */ for (uint8_t i = 0; i < teHeader.NumberOfSections; i++) { qlseek(li, headerPosition); EFI_IMAGE_SECTION_HEADER sectionHeader = {0}; qlread(li, §ionHeader, sizeof(EFI_IMAGE_SECTION_HEADER)); msg("Section name: %s\n", sectionHeader.Name); /* ok */ uint32_t position = sectionHeader.PointerToRawData - delta; msg("Position %x\n", position); qlseek(li, position); ea_t section_start = sectionHeader.VirtualAddress + teHeader.ImageBase - delta; ea_t section_end = 0; if (sectionHeader.Misc.VirtualSize > sectionHeader.SizeOfRawData) { section_end = sectionHeader.VirtualAddress + teHeader.ImageBase - delta + sectionHeader.Misc.VirtualSize; } else { section_end = sectionHeader.VirtualAddress + teHeader.ImageBase - delta + sectionHeader.SizeOfRawData; } msg("Section start: 0x%llx\n", section_start); msg("Section end: 0x%llx\n", section_end); file2base(li, position, section_start, section_end, 1); int bitness = -1; switch (teHeader.Machine) { case IMAGE_FILE_MACHINE_I386: bitness = 1; break; case IMAGE_FILE_MACHINE_X64: bitness = 2; break; default: bitness = 0; } const char *classType; if (qstrcmp((const char*)sectionHeader.Name, ".text") == 0) { classType = "CODE"; } else { classType = "DATA"; } add_segm(0, section_start, section_end, (const char*)sectionHeader.Name, classType); set_segm_addressing(get_segm_by_name((const char *)sectionHeader.Name), bitness); /* try to find the GUIDs in data section */ if (qstrcmp((const char *)sectionHeader.Name, ".data") == 0) { find_guids(section_start, section_end); } /* advance to next section */ headerPosition += sizeof(EFI_IMAGE_SECTION_HEADER); } /* configure the entrypoint address */ add_entry(teHeader.AddressOfEntryPoint + teHeader.ImageBase - delta, teHeader.AddressOfEntryPoint + teHeader.ImageBase - delta, "_start", 1); /* all done */ }
void idaapi PIC_run(int arg) { ea_t curr_addr; int n_funcz, i; func_t *curr_func; if ( is_first ) { got_addr = get_name_ea(BADADDR, got_name); if ( BADADDR == got_addr ) { got_addr = get_name_ea(BADADDR,got_name1); if ( BADADDR != got_addr ) { got_addr = get_long(got_addr); } else { got_addr = get_name_ea(BADADDR, got_name2); } } is_first = false; // 2 Nov 2005: dirty hack, bcs get_name_ea("_got") return BADADDR segment_t *s; if ( BADADDR == got_addr ) { s = get_segm_by_name(".got"); if ( s != NULL ) got_addr = s->startEA; } // 14 oct 2009 s = get_segm_by_name(".got.plt"); if ( s != NULL ) got_plt_addr = s->startEA; } if ( BADADDR == got_addr ) { msg("Cannot resolve _got address. Bad plugin initialization"); return; } #ifdef PIC_DEBUG RP_TRACE1( "got_addr %X\n", got_addr ); #endif switch (arg) { case 0: /* only function under current EA */ curr_addr = get_screen_ea(); #ifdef PIC_DEBUG RP_TRACE1( "curr_addr %X\n", curr_addr ); #endif /* next I had to resolve function */ curr_func = get_func(curr_addr); if ( NULL == curr_func ) { warning("Cannot operate not on function, address %X\n", curr_addr); return; } #if defined(PIC_DEBUG) || defined(PIC_SHOW) rp_log_fp = fopen(log_filename, "w+t"); #endif process_PIC(curr_func->startEA, curr_func->endEA); #if defined(PIC_DEBUG) || defined(PIC_SHOW) if ( NULL != rp_log_fp ) { fclose(rp_log_fp); rp_log_fp = NULL; } #endif break; case 1: /* process all defined functions */ #if defined(PIC_DEBUG) || defined(PIC_SHOW) rp_log_fp = fopen(log_filename, "w+t"); #endif n_funcz = get_func_qty(); if ( !n_funcz ) { warning("No functions defined!"); return; } for ( i = 0; i < n_funcz; i++ ) { curr_func = getn_func(i); if ( NULL == curr_func ) { RP_TRACE1("PIC: cannot get func N %d\n", i); continue; } process_PIC(curr_func->startEA, curr_func->endEA); } #if defined(PIC_DEBUG) || defined(PIC_SHOW) if ( NULL != rp_log_fp ) { fclose(rp_log_fp); rp_log_fp = NULL; } #endif break; default: warning("PIC: Unknown arg %d", arg); break; } /* switch */ }
static int notify(processor_t::idp_notify msgid, ...) { static int first_time = 1; 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: helper.create("$ intel 8051"); inf.mf = 1; // Set a big endian mode of the IDA kernel default: break; case processor_t::term: free_ioports(ports, numports); 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; inf.startIP = 0; for ( int i=0; i < qnumber(entries); i++ ) { if ( entries[i].proc > ptype ) continue; ea_t ea = inf.beginEA+entries[i].off; if ( isEnabled(ea) && get_byte(ea) != 0xFF ) { add_entry(ea, ea, entries[i].name, 1); set_cmt(ea, entries[i].cmt, 1); } } } } segment_t *scode = get_first_seg(); set_segm_class(scode, "CODE"); if ( ptype > prc_51 ) { AdditionalSegment(0x10000-256-128, 256+128, "RAM"); if ( scode != NULL ) { ea_t align = (scode->endEA + 0xFFF) & ~0xFFF; if ( getseg(align-7) == scode ) // the code segment size is { // multiple of 4K or near it uchar b0 = get_byte(align-8); // 251: // 0 : 1-source, 0-binary mode // 6,7: must be 1s // 82930: // 0 : 1-source, 0-binary mode // 7 : must be 1s // uchar b1 = get_byte(align-7); // 251 // 0: eprommap 0 - FE2000..FE4000 is mapped into 00E000..100000 // 1 - .............. is not mapped ............... // 1: must be 1 // 3: // 2: must be 1 // 4: intr 1 - upon interrupt PC,PSW are pushed into stack // 0 - upon interrupt only PC is pushed into stack // 5: must be 1 // 6: must be 1 // 7: must be 1 // 82930: // 3: must be 1 // 5: must be 1 // 6: must be 1 // 7: must be 1 // msg("b0=%x b1=%x\n", b0, b1); // if ( (b0 & 0x80) == 0x80 && (b1 & 0xEA) == 0xEA ) { // the init bits are correct char pname[sizeof(inf.procName)+1]; inf.get_proc_name(pname); char ntype = (b0 & 1) ? 's' : 'b'; char *ptr = tail(pname)-1; if ( ntype != *ptr && askyn_c(1, "HIDECANCEL\n" "The input file seems to be for the %s mode of the processor. " "Do you want to change the current processor type?", ntype == 's' ? "source" : "binary") > 0 ) { *ptr = ntype; first_time = 1; set_processor_type(pname, SETPROC_COMPAT); } } } } } // the default data segment will be INTMEM { segment_t *s = getseg(intmem); if ( s != NULL ) set_default_dataseg(s->sel); } if ( choose_ioport_device(cfgname, device, sizeof(device), parse_area_line0) ) set_device_name(device, IORESP_ALL); if ( get_segm_by_name("RAM") == NULL ) AdditionalSegment(256, 0, "RAM"); if ( get_segm_by_name("FSR") == NULL ) AdditionalSegment(128, 128, "FSR"); setup_data_segment_pointers(); } break; case processor_t::oldfile: setup_data_segment_pointers(); break; case processor_t::newseg: // make the default DS point to INTMEM // (8051 specific issue) { segment_t *newseg = va_arg(va, segment_t *); segment_t *intseg = getseg(intmem); if ( intseg != NULL ) newseg->defsr[rVds-ph.regFirstSreg] = intseg->sel; } break; case processor_t::newprc: { processor_subtype_t prcnum = processor_subtype_t(va_arg(va, int)); if ( !first_time && prcnum != ptype ) { warning("Sorry, it is not possible to change" // (this is 8051 specific) " the processor mode on the fly." " Please reload the input file" " if you want to change the processor."); return 0; } first_time = 0; ptype = prcnum; } break; case processor_t::newasm: // new assembler type { char buf[MAXSTR]; if ( helper.supval(-1, buf, sizeof(buf)) > 0 ) set_device_name(buf, IORESP_NONE); } break; case processor_t::move_segm:// A segment is moved // Fix processor dependent address sensitive information // args: ea_t from - old segment address // segment_t - moved segment { // ea_t from = va_arg(va, ea_t); // segment_t *s = va_arg(va, segment_t *); // Add commands to adjust your internal variables here // Most of the time this callback will be empty // // If you keep information in a netnode's altval array, you can use // node.altshift(from, s->startEA, s->endEA - s->startEA); // // If you have a variables pointing to somewhere in the disassembled program memory, // you can adjust it like this: // // asize_t size = s->endEA - s->startEA; // if ( var >= from && var < from+size ) // var += s->startEA - from; } break; case processor_t::is_sane_insn: // is the instruction sane for the current file type? // arg: int no_crefs // 1: the instruction has no code refs to it. // ida just tries to convert unexplored bytes // to an instruction (but there is no other // reason to convert them into an instruction) // 0: the instruction is created because // of some coderef, user request or another // weighty reason. // The instruction is in 'cmd' // returns: 1-ok, <=0-no, the instruction isn't // likely to appear in the program { int no_crefs = va_arg(va, int); return is_sane_insn(no_crefs); } } va_end(va); return(1); }