// add a struct/union even if its name already exists tid_t add_dup_struc(DieHolder &structure_holder, char const *name, uint32 *ordinal) { bool const is_union = structure_holder.get_tag() == DW_TAG_union_type; tid_t struc_id = add_struc(BADADDR, name, is_union); // failed to add? if(struc_id == BADNODE) { qstring new_name(name); while(struc_id == BADNODE) { new_name.append('_'); StrucCmp struc_cmp(new_name.c_str()); // check if there is an existing equal struct/union // with the same new name if(struc_cmp.equal(structure_holder)) { struc_id = struc_cmp.get_struc_id(); *ordinal = struc_cmp.get_ordinal(); } else { struc_id = add_struc(BADADDR, new_name.c_str(), is_union); } } } return struc_id; }
tid_t create_vtbl_struct(ea_t vtbl_addr, ea_t vtbl_addr_end, char* vtbl_name, uval_t idx, unsigned int* vtbl_len) { qstring struc_name = vtbl_name; tid_t id = add_struc(BADADDR, struc_name.c_str()); if (id == BADADDR) { struc_name.clear(); struc_name = askstr(HIST_IDENT, NULL, "Default name %s not correct. Enter other structure name: ", struc_name.c_str()); id = add_struc(BADADDR, struc_name.c_str()); set_struc_cmt(id, vtbl_name, true); } struc_t* new_struc = get_struc(id); if (!new_struc) return BADNODE; ea_t ea = vtbl_addr; int offset = 0; while (ea < vtbl_addr_end) { offset = ea - vtbl_addr; qstring method_name; ea_t method_ea = get_long(ea); if (method_ea == 0) break; if (!isEnabled(method_ea)) break; flags_t method_flags = getFlags(method_ea); char* struc_member_name = NULL; if (isFunc(method_flags)) { method_name = get_short_name(method_ea); if (method_name.length() != 0) struc_member_name = (char*)method_name.c_str(); } add_struc_member(new_struc, NULL, offset, dwrdflag(), NULL, 4); if (struc_member_name) { if (!set_member_name(new_struc, offset, struc_member_name)) { //get_name(NULL, method_ea, method_name, sizeof(method_name)); get_ea_name(&method_name, method_ea); set_member_name(new_struc, offset, struc_member_name); } } ea = ea + 4; flags_t ea_flags = getFlags(ea); if (has_any_name(ea_flags)) break; } return id; }
tid_t type_builder_t::get_structure(const qstring name) { tid_t struct_type_id = add_struc(BADADDR, name.c_str()); if (struct_type_id != 0 || struct_type_id != -1) { struc_t * struc = get_struc(struct_type_id); if(struc != NULL) { opinfo_t opinfo; opinfo.tid = struct_type_id; int j = 0; for(std::map<int, struct_filed>::iterator i = structure.begin(); i != structure.end() ; i ++) { VTBL_info_t vtbl; flags_t member_flgs = 0; if(i->second.size == 1) member_flgs = byteflag(); else if (i->second.size == 2) member_flgs = wordflag(); else if (i->second.size == 4) member_flgs = dwrdflag(); else if (i->second.size == 8) member_flgs = qwrdflag(); char field_name[258]; memset(field_name, 0x00, sizeof(field_name)); if((i->second.vftbl != BADADDR) && get_vbtbl_by_ea(i->second.vftbl, vtbl)) { qstring vftbl_name = name; vftbl_name.cat_sprnt("_VTABLE_%X_%p", i->second.offset, i->second.vftbl); tid_t vtbl_str_id = create_vtbl_struct(vtbl.ea_begin, vtbl.ea_end, (char *)vftbl_name.c_str(), 0); if (vtbl_str_id != BADADDR) { sprintf_s(field_name, sizeof(field_name), "vftbl_%d_%p", j, i->second.vftbl); int iRet = add_struc_member(struc, field_name, i->second.offset, member_flgs, NULL, i->second.size); member_t * membr = get_member_by_name(struc, field_name); if (membr != NULL) { tinfo_t new_type = create_typedef((char *)vftbl_name.c_str()); if(new_type.is_correct()) { smt_code_t dd = set_member_tinfo2(struc, membr, 0, make_pointer(new_type), SET_MEMTI_COMPATIBLE); } } } } else { sprintf_s(field_name, sizeof(field_name), "field_%X", i->second.offset); int iRet = add_struc_member(struc, field_name, i->second.offset, member_flgs, NULL, i->second.size); } j ++; } } } return struct_type_id; }
static bool idaapi make_vtbl_struct_cb(void *ud) { VTBL_info_t vtbl_t = vtbl_t_list[current_line_pos]; tid_t id = add_struc(BADADDR, vtbl_t.vtbl_name.c_str()); create_vtbl_struct(vtbl_t.ea_begin, vtbl_t.ea_end, (char*)vtbl_t.vtbl_name.c_str(), id); return true; }
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; }
struc_t * struct_create(int size) { struc_t *sptr; sptr = get_struc(add_struc(BADADDR, NULL, false)); if(!sptr) { msg("[idastruct] error: could not create structure\n"); return NULL; } return sptr; }
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); }
tid_t type_builder_t::get_structure(char * name) { tid_t struct_type_id = add_struc(BADADDR, name); if (struct_type_id != 0 || struct_type_id != -1) { struc_t * struc = get_struc(struct_type_id); if(struc != NULL) { sort_fields(structure); int offs = 0; opinfo_t opinfo; opinfo.tid = struct_type_id; for(unsigned int i = 0 ; i < structure.size() ; i ++) { if(structure[i].offset > offs) { offs = structure[i].offset; } flags_t member_flgs = 0; if(structure[i].size == 1) member_flgs = byteflag(); else if (structure[i].size == 2) member_flgs = wordflag(); else if (structure[i].size == 4) member_flgs = dwrdflag(); else if (structure[i].size == 8) member_flgs = qwrdflag(); char field_name[258]; memset(field_name, 0x00, sizeof(field_name)); sprintf_s(field_name, sizeof(field_name), "field_%d", i); int iRet = add_struc_member(struc, field_name, structure[i].offset, member_flgs, NULL, structure[i].size); offs += structure[i].size; } } } return struct_type_id; }
tid_t create_vtbl_struct(ea_t vtbl_addr, ea_t vtbl_addr_end, char* vtbl_name, uval_t idx, unsigned int* vtbl_len) { qstring struc_name = vtbl_name; //struc_name.append(qstring("_vtbl_struct")); tid_t id = add_struc(BADADDR, struc_name.c_str()); if (id == BADADDR) { struc_name.clear(); struc_name = askstr(HIST_IDENT, NULL, "Default name %s not correct. Enter other structure name: ", struc_name.c_str()); id = add_struc(BADADDR, struc_name.c_str()); set_struc_cmt(id, vtbl_name, true); } struc_t* new_struc = get_struc(id); if (!new_struc) return BADNODE; ea_t ea = vtbl_addr; ea_t offset = 0; while (ea < vtbl_addr_end) { offset = ea - vtbl_addr; qstring method_name; #ifndef __EA64__ ea_t method_ea = get_long(ea); // get function ea #else ea_t method_ea = get_64bit(ea); #endif if (method_ea == 0) break; if (!isEnabled(method_ea)) break; flags_t method_flags = getFlags(method_ea); char* struc_member_name = NULL; if (isFunc(method_flags)) { method_name = f_get_short_name(method_ea); // this line crash ida when compare qstring with null if (method_name.length() != 0) { struc_member_name = (char*)method_name.c_str(); } } #ifndef __EA64__ add_struc_member(new_struc, NULL, offset, dwrdflag(), NULL, 4); #else add_struc_member(new_struc, NULL, offset, qwrdflag(), NULL, sizeof(UINT64)); #endif if (struc_member_name) { if (!set_member_name(new_struc, offset, struc_member_name)) { //get_name(NULL, method_ea, method_name, sizeof(method_name)); f_get_ea_name(&method_name, method_ea); set_member_name(new_struc, offset, struc_member_name); } } #ifndef __EA64__ ea = ea + 4; #else ea = ea + sizeof(UINT64); #endif flags_t ea_flags = getFlags(ea); if (has_any_name(ea_flags)) break; } return id; }