bool idaapi check_subtype(const VTBL_info_t &vtbl_info, const qstring &subtype_name) { bool bResult = false; qstring search_str; search_str.sprnt("_%p", vtbl_info.ea_begin); tid_t type_id = get_struc_id(subtype_name.c_str()); if (type_id != BADADDR) { struc_t * struc_type = get_struc(type_id); if (struc_type != NULL) { // enumerate members for (ea_t offset = get_struc_first_offset(struc_type); offset != BADADDR; offset = get_struc_next_offset(struc_type, offset)) { member_t * member_info = get_member(struc_type, offset); if (member_info != NULL) { qstring member_name = get_member_name2(member_info->id); if (member_name.find(search_str, 0) != -1) { bResult = true; break; } } } } } return bResult; }
void idaapi dump_type_info(int file_id, const VTBL_info_t& vtbl_info, const qstring& type_name, const std::map<ea_t, VTBL_info_t>& vtbl_map) { struc_t * struc_type = get_struc(get_struc_id(type_name.c_str())); if (!struc_type) return; qstring file_entry_key; qstring key_hash; bool filtered = false; get_struct_key(struc_type, vtbl_info, file_entry_key, filtered, vtbl_map); get_hash_of_string(file_entry_key, key_hash); if (filtered) return; qstring file_entry_val; tinfo_t new_type = create_typedef(type_name.c_str()); if (new_type.is_correct() && new_type.print(&file_entry_val, NULL, PRTYPE_DEF | PRTYPE_1LINE)) { qstring line; line = key_hash + ";" + file_entry_key + ";"; line.cat_sprnt("%a;", vtbl_info.ea_begin); line += file_entry_val + ";"; if (rtti_vftables.count(vtbl_info.ea_begin) != 0) { VTBL_info_t vi = rtti_vftables[vtbl_info.ea_begin]; line += vi.vtbl_name; } line.rtrim(); line += "\r\n"; qwrite(file_id, line.c_str(), line.length()); } }
void idaapi run(int arg) { char *st_name = "struc_2"; char buf[MAXSTR]; static char st_name_buf[100]; if (arg == 0) { strcpy(buf, st_name); CWin32InputBox::InputBox("Struct name", "Enter struct name:", st_name_buf, sizeof(st_name_buf)); st_name = st_name_buf; } size_t st_qty = get_struc_qty(); msg("we have: %d structs\n", st_qty); // find the structure by name tid_t id = get_struc_id(st_name); // get the size of the structure asize_t st_sz = get_struc_size(id); msg("sizeof(%s) = %d\n", st_name, st_sz); struc_t *st = get_struc(id); enum_members2(st); return; }
tid_t idaapi merge_types(qvector<qstring> types_to_merge, qstring type_name) { tid_t struct_type_id = BADADDR; std::set<ea_t> offsets; if (types_to_merge.size() != 0) { struct_type_id = add_struc(BADADDR, type_name.c_str()); if (struct_type_id != 0 || struct_type_id != BADADDR) { struc_t * struc = get_struc(struct_type_id); if (struc != NULL) { qvector<qstring>::iterator types_iter; for (types_iter = types_to_merge.begin(); types_iter != types_to_merge.end(); types_iter++) { tid_t type_id = get_struc_id((*types_iter).c_str()); if (type_id != BADADDR) { struc_t * struc_type = get_struc(type_id); if (struc_type != NULL) { // enumerate members for (ea_t offset = get_struc_first_offset(struc_type); offset != BADADDR; offset = get_struc_next_offset(struc_type, offset)) { member_t * member_info = get_member(struc_type, offset); if (member_info != NULL) { if (offsets.count(member_info->soff) == 0) { qstring member_name = get_member_name2(member_info->id); asize_t member_size = get_member_size(member_info); if (member_name.find("vftbl_", 0) != -1) { tinfo_t tif; if (get_member_tinfo2(member_info, &tif)) { add_struc_member(struc, member_name.c_str(), member_info->soff, dwrdflag(), NULL, member_size); member_t * membr = get_member(struc, member_info->soff); if (membr != NULL) { set_member_tinfo2(struc, membr, 0, tif, SET_MEMTI_COMPATIBLE); } } } else { add_struc_member(struc, member_name.c_str(), member_info->soff, member_info->flag, NULL, member_size); } offsets.insert(member_info->soff); } } } } } } } } } return struct_type_id; }
tid_t idaapi merge_types(const qvector<qstring>& types_to_merge, const qstring& type_name) { tid_t struct_type_id = BADADDR; if (types_to_merge.empty()) return struct_type_id; std::set<ea_t> offsets; struct_type_id = add_struc(BADADDR, type_name.c_str()); if (struct_type_id == BADADDR) return struct_type_id; struc_t * struc = get_struc(struct_type_id); if (!struc) return struct_type_id; for (auto types_iter = types_to_merge.begin(), end = types_to_merge.end(); types_iter != end; ++types_iter) { struc_t * struc_type = get_struc(get_struc_id(types_iter->c_str())); if (!struc_type) continue; // enumerate members for ( ea_t offset = get_struc_first_offset(struc_type) ; offset != BADADDR ; offset = get_struc_next_offset(struc_type, offset)) { member_t * member_info = get_member(struc_type, offset); if (!member_info) continue; if (offsets.count(member_info->soff) == 0) { qstring member_name = get_member_name(member_info->id); asize_t member_size = get_member_size(member_info); if (member_name.find("vftbl_", 0) != -1) { tinfo_t tif; if (get_member_tinfo(&tif, member_info)) { add_struc_member(struc, member_name.c_str(), member_info->soff, dword_flag(), NULL, member_size); if (member_t * membr = get_member(struc, member_info->soff)) { set_member_tinfo(struc, membr, 0, tif, SET_MEMTI_COMPATIBLE); } } } else { add_struc_member(struc, member_name.c_str(), member_info->soff, member_info->flag, NULL, member_size); } offsets.insert(member_info->soff); } } } return struct_type_id; }
//-------------------------------------------------------------------------- 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); }
static void declare_parameter_types(ea_t ea, int count) { static const char class_name[] = "CMethodDef"; struc_t *sptr = get_struc(get_struc_id(class_name)); if ( sptr == NULL ) { sptr = get_struc(add_struc(-1, class_name)); if ( sptr == NULL ) return; add_struc_member(sptr, "methodParameterDef", -1, wordflag(), NULL, 2); add_struc_member(sptr, "handlerTypeDef", -1, byteflag(), NULL, 1); } size_t size = get_struc_size(sptr); doStruct(ea, size*count, sptr->id); }
bool idaapi check_subtype(VTBL_info_t vtbl_info, qstring subtype_name) { qstring search_str; search_str.sprnt("_%a", vtbl_info.ea_begin); struc_t * struc_type = get_struc(get_struc_id(subtype_name.c_str())); if (!struc_type) return false; // enumerate members for ( ea_t offset = get_struc_first_offset(struc_type) ; offset != BADADDR ; offset = get_struc_next_offset(struc_type, offset)) { member_t * member_info = get_member(struc_type, offset); if (!member_info) continue; qstring member_name = get_member_name(member_info->id); if (member_name.find(search_str, 0) != member_name.npos) return true; } return false; }
void idaapi dump_type_info(int file_id, VTBL_info_t vtbl_info, qstring type_name, std::map<ea_t, VTBL_info_t> vtbl_map) { tid_t type_id = get_struc_id(type_name.c_str()); if (type_id != BADADDR) { struc_t * struc_type = get_struc(type_id); if(struc_type != NULL) { qstring file_entry_key; qstring key_hash; bool filtered = false; get_struct_key(struc_type, vtbl_info, file_entry_key, filtered, vtbl_map); get_hash_of_string(file_entry_key, key_hash); if (!filtered) { qstring file_entry_val; tinfo_t new_type = create_typedef(type_name.c_str()); if(new_type.is_correct()) { if (new_type.print(&file_entry_val, NULL, PRTYPE_DEF | PRTYPE_1LINE)) { qstring line; line = key_hash + ";" + file_entry_key + ";"; line.cat_sprnt("%p;", vtbl_info.ea_begin); line += file_entry_val + ";"; if (rtti_vftables.count(vtbl_info.ea_begin) != 0) { vftable::vtinfo vi = rtti_vftables[vtbl_info.ea_begin]; line += vi.type_info; } line.rtrim(); line += "\r\n"; qwrite(file_id, line.c_str(), line.length()); } } } } } }
// check if there is a typedef with a given name and equivalent content in the db // equivalent content means e.g. structures, unions and enums have the same members // return its ordinal if the typedef is found. (0 otherwise) uint32 get_equivalent_typedef_ordinal(DieHolder &typedef_holder, uint32 const type_ordinal) { uint32 ordinal = 0; char const *typedef_name = typedef_holder.get_name(); type_t const *type = NULL; char const *name = NULL; bool ok = get_numbered_type(idati, type_ordinal, &type); if(ok) { type_t const *existing_type = NULL; // already an existing type with the same name? ok = get_named_type(idati, typedef_name, NTF_TYPE | NTF_NOBASE, &existing_type); if(ok) { // existing type is a typedef? if(is_type_typedef(*existing_type)) { // typedef to a structure/union? if(is_type_struni(*type)) { name = get_typedef_name(existing_type); if(name != NULL) { tid_t struc_id = get_struc_id(name); ok = (struc_id != BADNODE); if(ok) { Dwarf_Off offset = 0; ok = diecache.get_type_offset(type_ordinal, &offset); if(ok) { DieHolder structure_holder(typedef_holder.get_dbg(), offset); StrucCmp struc_cmp(name); ok = struc_cmp.equal(structure_holder); } } } } // typedef to an enum else if(is_type_enum(*type)) { name = get_typedef_name(existing_type); if(name != NULL) { enum_t enum_id = get_enum(name); ok = (enum_id != BADNODE); if(ok) { Dwarf_Off offset = 0; ok = diecache.get_type_offset(type_ordinal, &offset); if(ok) { DieHolder enumeration_holder(typedef_holder.get_dbg(), offset); EnumCmp enum_cmp(name); ok = enum_cmp.equal(enumeration_holder); } } } } } } } if(name != NULL) { if(ok) { ordinal = get_type_ordinal(idati, typedef_name); DEBUG("found equivalent typedef typedef_name='%s' name='%s' type_ordinal=%u ordinal=%u\n", typedef_name, name, type_ordinal, ordinal); } } return ordinal; }
int RP_mapping::process_string(char *str, int ln) { char *arg1, *arg2; for ( arg1 = arg2 = str; !isspace( *arg2) && *arg2; arg2++ ) ; if ( !*arg2 ) return 0; *arg2++ = 0x0; if ( !*arg2) return 0; for ( ; *arg2 && isspace(*arg2); arg2++ ) ; if ( !*arg2 ) return 0; // next - just trim all spaces at end char *ptr = arg2 + 1; for ( ; !isspace(*ptr) && *ptr; ptr++ ) ; *ptr = 0x0; /* O`k, now arg1 contains address or name and arg2 contains name of struct */ // first check for struct presence tid_t tid = get_struc_id(arg2); if ( BADADDR == tid ) { if ( verbose ) msg("Cannot find struct '%s'\n", arg2); return 0; } // next try to resolve first arg as name ea_t ea = get_name_ea(BADADDR, arg1); if ( ea != BADADDR ) { /* first check for already presenting */ dnode_t *again = is_presented(ea); if ( NULL != again ) { if ( verbose ) msg("Warning, address %X already in dictionary, overwrite\n", ea); dnode_put(again, (void *)tid); } else { /* place to dict new mapping name -> tid_t */ dict_alloc_insert(mapping, (const void *)ea, (void *)tid); } #ifdef RP_DEBUG msg("Mapping %X (%s) -> %s (%X) \n", ea, arg1, arg2, tid); #endif return 1; } /* well may be we shold add yet one underscore at begin of name ? */ { int len = strlen(arg1); char *dup = (char *)qalloc(len + 2); *dup = '_'; strcpy(dup + 1, arg1); ea = get_name_ea(BADADDR, dup); if ( BADADDR != ea ) { dnode_t *again = is_presented(ea); if ( NULL != again ) { if ( verbose ) msg("Warning, address %X already in dictionary, overwrite\n", ea); dnode_put(again, (void *)tid); } else { dict_alloc_insert(mapping, (const void *)ea, (void *)tid); } #ifdef RP_DEBUG msg("Mapping %X (%s) -> %s (%X) \n", ea, dup, arg2, tid); #endif qfree(dup); return 1; } qfree(dup); } /* well - may be we has address ? */ if ( *arg1 == '0' && ( arg1[1] == 'x' || arg1[1] == 'X' ) ) { arg1 += 2; if ( ! *arg1 ) { if ( verbose ) msg("Line %d. Bad address '%s'\n", ln, arg1 - 2); return 0; } } char *notused; ea = strtol(arg1, ¬used, 0x10); if ( !ea ) { if ( verbose ) msg("Line %d. Bad address '%s'\n", ln, arg1); return 0; } // O`k it seems that we really has some address. Lets check it if ( NULL == getseg(ea) ) { if ( verbose ) msg("Line %d. Address %X is not in your file\n", ln, ea); return 0; } dnode_t *again = is_presented(ea); if ( NULL != again ) { if ( verbose ) msg("Warning, address %X already in dictionary, overwrite\n", ea); dnode_put(again, (void *)tid); } else { dict_alloc_insert(mapping, (const void *)ea, (void *)tid); } #ifdef RP_DEBUG msg("Mapping %X -> %s (%X) \n", ea, arg2, tid); #endif return 1; }