//------------------------------------------------------------------ static const char *idaapi parse_area_line(const char *line, char *buf, size_t bufsize) { char word[MAXSTR]; char aclass[MAXSTR]; ea_t ea1, ea2; if ( sscanf(line, "area %s %s %" FMT_EA "i:%" FMT_EA "i", aclass, word, &ea1, &ea2) == 4 ) { int ram = 0; int rom = 0; int eprom = 0; int eeprom = 0; static const char format[] = "RAM=%d ROM=%d EPROM=%d " CUSTOM1 "=%d"; sscanf(buf, format, &ram, &rom, &eprom, &eeprom); int size = ea2 - ea1; if ( stristr(word, "RAM") != NULL ) ram += size; else if ( stristr(word, CUSTOM1) != NULL ) eeprom += size; else if ( stristr(word, "EPROM") != NULL ) eprom += size; else if ( stristr(word, "ROM") != NULL ) rom += size; if ( ram || rom || eeprom || eeprom ) qsnprintf(buf, bufsize, format, ram, rom, eprom, eeprom); else buf[0] = '\0'; if ( (respect_info & IORESP_AREA) != 0 && get_segm_qty() != 0 ) { #ifdef I8051 if ( ( stristr(word, "FSR") != NULL ) ||( stristr(word, "RAM") != NULL )) { AdditionalSegment( ea2-ea1, ea1, word ); } else #endif { sel_t sel = allocate_selector(0); add_segm(sel, ea1, ea2, word, aclass); } if ( ea2-ea1 > 0xFFFF ) set_segm_addressing(getseg(ea1), true); } return NULL; } return "syntax error"; }
static int notify(processor_t::idp_notify msgid, ...) { 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("$ pic"); helper.supval(0, device, sizeof(device)); default: break; case processor_t::term: free_mappings(); free_ioports(ports, numports); break; case processor_t::newfile: // new file loaded { segment_t *s0 = get_first_seg(); if ( s0 != NULL ) { set_segm_name(s0, "CODE"); dataseg = AdditionalSegment(0x200, 0, "DATA"); segment_t *s1 = get_next_seg(s0->startEA); SetDefaultRegisterValue(s0, BANK, 0); SetDefaultRegisterValue(s1, BANK, 0); SetDefaultRegisterValue(s0, PCLATH, 0); SetDefaultRegisterValue(s1, PCLATH, 0); SetDefaultRegisterValue(s0, PCLATU, 0); SetDefaultRegisterValue(s1, PCLATU, 0); setup_device(IORESP_INT); apply_symbols(); } } break; case processor_t::oldfile: // old file loaded idpflags = (ushort)helper.altval(-1); dataseg = helper.altval(0); create_mappings(); for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->startEA) ) { if ( s->defsr[PCLATH-ph.regFirstSreg] == BADSEL ) s->defsr[PCLATH-ph.regFirstSreg] = 0; } break; case processor_t::closebase: case processor_t::savebase: helper.altset(0, dataseg); helper.altset(-1, idpflags); helper.supset(0, device); break; case processor_t::newprc: // new processor type { int n = va_arg(va, int); static bool set = false; if ( set ) return 0; set = true; if ( ptypes[n] != ptype ) { ptype = ptypes[n]; ph.cnbits = 12 + 2*n; } switch ( ptype ) { case PIC12: register_names[PCLATH] = "status"; cfgname = "pic12.cfg"; break; case PIC14: cfgname = "pic14.cfg"; break; case PIC16: register_names[BANK] = "bsr"; cfgname = "pic16.cfg"; idpflags = 0; ph.cnbits = 8; ph.regLastSreg = PCLATU; break; default: error("interr in setprc"); break; } } break; case processor_t::newasm: // new assembler type break; case processor_t::newseg: // new segment break; } va_end(va); return 1; }
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); }