示例#1
0
void idaapi matched_structs_with_offsets::get_type_line(void *obj,uint32 n,char * const *arrptr)
{
	matched_structs_with_offsets & ms = *(matched_structs_with_offsets*)obj;
	if (n==0)
	{
		qstrncpy(arrptr[0], "member", MAXSTR);
		qstrncpy(arrptr[1], "type", MAXSTR);		
	}
	else
	{
		char name[MAXSTR];
		name[0]=0;

		char type_str[MAXSTR];
		type_str[0]=0;

		tid_t id = ms.idcka[n-1];
		struc_t * struc = get_struc(id);
		print_struct_member_name(struc, ms.offset, name, sizeof(name));
		member_t * member = 0;
		if(struct_get_member(get_struc(id), ms.offset, &member) && member)
		{
			//typestring type;
			tinfo_t type;
			if(get_member_type(member, &type))
			{
				type.print(new qstring(type_str));
			}
		}
		qstpncpy(arrptr[0],  name, MAXSTR);
		qstpncpy(arrptr[1],  type_str, MAXSTR);		
	}	
}
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;
}
示例#4
0
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);
}
示例#5
0
//--------------------------------------------------------------------------
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);
}
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;
}
示例#7
0
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;
}
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());
	}
}
示例#9
0
void StrucCmp::add_all_members(void) throw()
{
  if(m_struc_id != BADNODE)
  {
    struc_t *sptr = get_struc(m_struc_id);
    ssize_t const struc_len = get_struc_name(m_struc_id, NULL, 0);

    for(size_t idx = 0; idx < sptr->memqty; ++idx)
    {
      member_t *mptr = &(sptr->members[idx]);

      // get_member_name crashes when given a NULL pointer...
      // we need to get the "struct.field" name and
      // substract the "struct." part
      // len is without the '\0' character
      ssize_t len = get_member_fullname(mptr->id, NULL, 0);

      if(len != -1)
      {
        len -= struc_len;

        char *buf = static_cast<char *>(qalloc(len));
        if(buf != NULL)
        {
          get_member_name(mptr->id, buf, len);
          m_members[buf] = m_is_union ? 0 : mptr->soff;
        }
      }
    }
  }
}
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;
}
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;
}
static int GetTypeOfStructInstance(ea_t ea, ea_t head, flags_t flags)
{
	typeinfo_t ti;
	if (!get_typeinfo(head, 0, flags, &ti)) return T_UNK;
	struc_t *sptr = get_struc(ti.tid);
	if (!sptr) return T_UNK;
	member_t *mptr = get_best_fit_member(sptr, ea - head);
	if (!mptr || mptr->soff != ea - head) return T_UNK;

	return GetMemberType(mptr);

}
示例#13
0
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;
}
示例#14
0
char * idaapi matched_structs::get_type_line(void *obj, uint32 n, char *buf)
{
	matched_structs & ms = *(matched_structs*)obj;
	if (n==0)
		qstpncpy( buf, "type", MAXSTR );
	else
	{
		qstring name;
;
		tid_t id =  ms.idcka[n-1];
		struc_t * struc = get_struc(id);
		if (struc)
			get_struc_name(&name, id);
		//asize_t size = get_struc_size(id);
		qsnprintf(buf, MAXSTR, "%s", name.c_str());
	}
	return buf;
}
示例#15
0
//----------------------------------------------------------------------------
// gen_snapshot - generate "snapshot" of landscape configuration at a single point in time
//----------------------------------------------------------------------------
void gen_snapshot( char *runname, int year, struct image_header out_head,
    int snapsum, int transsum )
{
    int row;                // row counter
    int col;                // column counter
    int index;              // array index
    short int struc;        // forest structure index
    char yearstr[10];       // current summary year
    char outfilename[30];   // output file name

    // open output file
    strcpy(outfilename, runname);
    itoa(year, yearstr, 10);
    strcat(outfilename, yearstr);
    strcat(outfilename, ".gis");

    // write grid cell information to temporary grids
   	for(row=0; row<maxrow; row++) {
		for(col=0; col<maxcol; col++) {
			index=row*maxcol + col;
            if(buffer[index] == 1) {
                struc = get_struc(index);
                temp[index] = (unsigned char)struc;
            } else {
                temp[index] = 0;
            }

        }
    }
	
	//Added by Ashis 12/28/2012
	// write lcc info into temp grid

	merg_lccSnapshot();

    // write grids to output files
    if (snapsum > 0) {
        write_grid(outfilename, temp, out_head);
    }

    return;
}
示例#16
0
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;
}
示例#17
0
tid_t add_class(tid_t tid_of_struc)
{
	//classes are built on top of structures, make sure there is one before continuing
	if(!get_struc(tid_of_struc))
		return BADNODE;
	if(get_class(tid_of_struc))
	{
		return tid_of_struc;	
	}

	class_t clas;
	clas.flags = 0;
	clas.tid = tid_of_struc;
	clas.functions_ea.clear();
	clas.parents_tid.clear();
	clas.virt_table_ea = BADADDR;
	save_class(&clas);
	//DONE: add to classes index
	add_class_at_idx(tid_of_struc, BADNODE);
	return tid_of_struc;
}
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());
					}
				}
			}
		}
	}
}
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;
}
示例#21
0
std::vector<IDAStructure> GetStructsFromDb()
{
    std::vector<IDAStructure> structures;

    constexpr size_t bufferSize = 256;
    std::array<char, bufferSize> buffer;

    for (auto i = get_first_struc_idx(); i != -1; i = get_next_struc_idx(i))
    {
        IDAStructure newStruct;
        const struc_t* idaStruct = get_struc(get_struc_by_idx(i));

        get_struc_name(idaStruct->id, buffer.data(), bufferSize);
        newStruct.m_name = std::string(buffer.data());

        get_struc_cmt(idaStruct->id, true, buffer.data(), bufferSize);
        newStruct.m_comment = std::string(buffer.data());

        newStruct.m_size = get_struc_size(idaStruct->id);

        msg("Struct %d = %s (%s) [%d bytes]\n", i, newStruct.m_name.c_str(), newStruct.m_comment.c_str(), newStruct.m_size);

        size_t offset = 0;
        member_t* idaStructMember = get_member(idaStruct, offset);

        while (idaStructMember != nullptr)
        {
            IDAStructure::Member newMember;

            get_member_fullname(idaStructMember->id, buffer.data(), bufferSize);
            newMember.m_name = std::string(buffer.data());

            {
                tinfo_t typeInfo;
                get_member_tinfo2(idaStructMember, &typeInfo);

                qstring typeName;

                if (typeInfo.get_type_name(&typeName))
                {
                    newMember.m_type = std::string(typeName.c_str());
                }
                else
                {
                    newMember.m_type = "undefined";
                }
            }

            get_member_cmt(idaStructMember->id, true, buffer.data(), bufferSize);
            newMember.m_comment = std::string(buffer.data());

            newMember.m_size = get_member_size(idaStructMember);     
            offset += newMember.m_size;

            msg("   %s {%s} (%s) [%d bytes]\n", newMember.m_name.c_str(), newMember.m_type.c_str(), newMember.m_comment.c_str(), newMember.m_size);

            newStruct.m_members.push_back(std::move(newMember));
            idaStructMember = get_member(idaStruct, offset);
        }

        structures.push_back(std::move(newStruct));

    }

    return std::move(structures);
}