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;
}
예제 #2
0
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;
}
예제 #3
0
/*
 * ===  FUNCTION  ======================================================================
 *         Name:  map_over_members
 *  Description:  Calls the function referred to by pointer 'func' on each
 *  member of an archive file.
 *
 *  Pre:  The file referred to by fd is open and has the necessary permissions
 *  and read/write attributes to perform 'func' on its contents.

 *  It's ugly, but it (mostly) works.  Once I had gotten down the basics of iterating
 *  over the archive file, I didn't want to have to repeat the logic separately for
 *  append, print, and delete.  That's why the function pointer is so darn hideous. I'm
 *  sure there's better way to do this, but I haven't learned it yet --- obviously :).
 * =====================================================================================
 */
static off_t
map_over_members(int fd, void (*func)(int, struct ar_hdr *, char **, int, int),
        char **files, int count, int temp_fd)
{
    struct ar_hdr hdr;
    off_t hdr_off, member_off, member_size;
    off_t ar_size = get_file_size(fd);

    /* First member header should be just
     * past archive magic header */
    if((hdr_off = seek_past_armag(fd)) == -1)
        return -1;

    while((member_off = get_hdr(fd, hdr_off, SEEK_SET, &hdr)) != -1) {

        /* Get member file's size in preparation
         * for next jump */
        member_size = get_member_size(&hdr);

        /* Here to help with diagnostics */
        /*
        print_member_name(&hdr);
        printf("member offset: %lld\n", (long long)member_off);
        printf("archive size: %lld\n", (long long)ar_size);
        */

        func(fd, &hdr, files, count, temp_fd);

        /* Make sure we're just before the member
         * file's contents */
        lseek(fd, member_off, SEEK_SET);

        /* Align jump to even bit size */
        member_size = member_size % 2 ? member_size + 1 : member_size;

        /* Set hdr_off to next header's offset;
         * exit loop if we're going to hit the
         * archive's boundary */
        if((hdr_off = member_off + member_size) >= ar_size)
            break;
    }

    /* Return to the beginning of the archive */
    return lseek(fd, 0, SEEK_SET);
}
예제 #4
0
/*
 * ===  FUNCTION  ======================================================================
 *         Name:  retain_member
 *  Description:  Function to be passed to map_over_members from delete_files.
 *  NULLs out a filename in 'files' and returns if there is a match to an
 *  archive member.  Otherwise, copies the ar_hdr struct and the subsequent
 *  file data to the temporary file referred to by 'temp_fd'.
 *
 *  Pre: 'temp_fd' refers to a file that exists and is writable; 'arch' refers
 *  to a file that exists and is readable.
 * =====================================================================================
 */
static void
retain_member(int arch, struct ar_hdr *hdr, char **files, int count, int temp_fd)
{
    char fname[SARFNAME+1];
    get_hdr_attr(hdr, name_attr, fname, SARFNAME+1);

    int match = match_fnames(fname, files, count, strcmp);

    /* If there was no match, set
     * files to NULL so that delete_files
     * can tell user that no file was found.
     * Otherwise, return so that we don't copy
     * the file. */
    if(match != -1) {
        files[match] = NULL;
        return;
    }

    /* Write header to temporary file */
    if(write(temp_fd, hdr, SARFHDR) == -1) {
        fprintf(stderr, "error writing to file\n");
        perror("write");
        goto cleanup;
    }

    size_t to_write = get_member_size(hdr);
    write_to_arch(arch, temp_fd, to_write);

    return;

cleanup:
    if(close(arch) == -1) {
        perror("close");
        fprintf(stderr, "error closing archive file\n");
    }
    if(close(temp_fd) == -1) {
        perror("close");
        fprintf(stderr, "error closing temporary file\n");
    }
    return;
}
예제 #5
0
void get_struct_key(struc_t * struc_type, const VTBL_info_t& vtbl_info, qstring &file_entry_key, bool &filtered, const std::map<ea_t, VTBL_info_t>& vtbl_map) {
	qstring sub_key;
	qstring vtables_sub_key;
	int vftbales_num = 0;
	int members_count = 0;
	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_name(member_info->id);
			asize_t member_size = get_member_size(member_info);

			if (member_name.find("vftbl_", 0) != -1) {

				ea_t vtable_addr = 0;
				int i;

				if (qsscanf(member_name.c_str(), "vftbl_%d_%" FMT_EA "x", &i, &vtable_addr) > 0) {
					if (vtbl_map.count(vtable_addr) != 0) {
						vtables_sub_key.cat_sprnt("_%d", vtbl_map.at(vtable_addr).methods);
					}
				}

				vftbales_num ++;
			}

			sub_key.cat_sprnt("_%d", member_size);

			members_count ++;
		}
	}
	file_entry_key.sprnt("t_%d_%d", vtbl_info.methods, vftbales_num);
	file_entry_key += vtables_sub_key;
	file_entry_key += sub_key;

	if (members_count < STRUCT_DUMP_MIN_MEMBER_COUNT)
		filtered = true;
}
예제 #6
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);
}
예제 #7
0
static void
structprobe(Dwarf *dw, Dwarf_Die *structdie)
{
	Dwarf_Die memdie;
	Dwarf_Word lastoff = 0, structsize;
	unsigned cline, members, nholes;
	size_t memsz, holesz;
	int x;

	(void)dw;

	cline = members = nholes = 0;
	memsz = holesz = 0;

	printf("struct %s {\n", dwarf_diename(structdie));

	if (dwarf_aggregate_size(structdie, &structsize) == -1)
		dwarf_err(EX_DATAERR, "dwarf_aggregate_size");

	if (dwarf_child(structdie, &memdie)) {
		printf("XXX ???\n");
		exit(EX_DATAERR);
	}

	do {
		Dwarf_Attribute type_attr, base_type_attr;
		Dwarf_Die type_die, base_type_die;
		char type_name[128], mem_name[128], ptr_suffix[32] = { '\0' };
		const char *type_tag = "";
		const char *type = NULL;
		unsigned type_ptrlevel = 0;

		Dwarf_Word msize, off;

		if (dwarf_tag(&memdie) != DW_TAG_member)
			continue;

		members++;
		/*
		 * TODO: Handle bitfield members. DW_AT_bit_offset,
		 * DW_AT_bit_size;
		 */

	 	/* Chase down the type die of this member */
		get_dwarf_attr(&memdie, DW_AT_type, &type_attr, &type_die);

		/* Member offset ... */
		if (get_member_offset(&memdie, &off) == -1)
			dwarf_err(EX_DATAERR, "%s", dwarf_diename(&memdie));

		/* Member size. */
		if (get_member_size(&type_die, &msize) == -1)
			dwarf_err(EX_DATAERR, "get_member_size");

		/* Format name; 'struct foo', 'enum bar', 'char **', etc. */
		if (isstruct(dwarf_tag(&type_die))) {
			type_tag = "struct ";
			type = dwarf_diename(&type_die);
		} else if (dwarf_tag(&type_die) == DW_TAG_enumeration_type) {
			type_tag = "enum ";
			type = dwarf_diename(&type_die);
		} else if (dwarf_tag(&type_die) == DW_TAG_pointer_type) {
			unsigned i;

			do {
				if (dwarf_tag(&type_die) == DW_TAG_pointer_type)
					type_ptrlevel++;
				else if (isstruct(dwarf_tag(&type_die)))
					type_tag = "struct ";
				else if (dwarf_tag(&type_die) == DW_TAG_enumeration_type)
					type_tag = "enum ";
				else
					printf("!!! XXX ignored pointer qualifier TAG %#x\n",
					    dwarf_tag(&type_die));

				/*
				 * Pointers to basic types still need some
				 * work. Clang doesn't emit an AT_TYPE for
				 * 'void*,' for example.
				 */
				if (!dwarf_hasattr(&type_die, DW_AT_type))
					break;

				get_dwarf_attr(&type_die, DW_AT_type,
				    &base_type_attr, &base_type_die);
				type_die = base_type_die;
				type_attr = base_type_attr;
			} while (dwarf_tag(&type_die) != DW_TAG_base_type);

			type = dwarf_diename(&type_die);
			if (type_ptrlevel > sizeof(ptr_suffix) - 2)
				type_ptrlevel = sizeof(ptr_suffix) - 2;
			ptr_suffix[0] = ' ';
			for (i = 1; i <= type_ptrlevel; i++)
				ptr_suffix[i] = '*';
			ptr_suffix[i] = '\0';
		} else
			type = dwarf_diename(&type_die);

		if (type == NULL)
			type = "<anonymous>";

		snprintf(type_name, sizeof(type_name), "%s%s%s", type_tag,
		    type, ptr_suffix);

		if (off != lastoff) {
			printf("\n\t/* XXX %ld bytes hole, try to pack */\n\n", off - lastoff);
			nholes++;
			holesz += (off - lastoff);
		}

		snprintf(mem_name, sizeof(mem_name), "%s;",
		    dwarf_diename(&memdie));

		printf("\t%-27s%-21s /* %5ld %5ld */\n", type_name, mem_name,
		    (long)off, (long)msize);
		memsz += msize;

		lastoff = off + msize;
		if (lastoff / cachelinesize > cline) {
			int ago = lastoff % cachelinesize;
			cline = lastoff / cachelinesize;

			if (ago)
				printf("\t/* --- cacheline %u boundary (%ld "
				    "bytes) was %d bytes ago --- */\n", cline,
				    (long)cline * cachelinesize, ago);
			else
				printf("\t/* --- cacheline %u boundary (%ld "
				    "bytes) --- */\n", cline, (long)cline *
				    cachelinesize);
		}
	} while ((x = dwarf_siblingof(&memdie, &memdie)) == 0);
	if (x == -1)
		dwarf_err(EX_DATAERR, "dwarf_siblingof");

	printf("\n\t/* size: %lu, cachelines: %u, members: %u */\n",
	    structsize, cline + 1, members);
	printf("\t/* sum members: %zu, holes: %u, sum holes: %zu */\n", memsz,
	    nholes, holesz);
	printf("\t/* last cacheline: %lu bytes */\n", lastoff % cachelinesize);

	printf("};\n");
}
예제 #8
0
void enum_members2(struc_t *st)
{
  char buf[MAXSTR];
  type_t type[MAXSTR] = {0};
  int gap_cnt = 1;

  asize_t ofs = 0, gapend = BADADDR, gapstart = BADADDR;

  for (size_t i=0;i<st->memqty;i++)
  {
    member_t &mem = st->members[i];

    // unexpected beginning of member?
    if (mem.soff != ofs)
    {
//      msg("gap detected @ %a!\n", ofs);
      gapstart = ofs;
    }

    if (gapstart != BADADDR)
    {
      gapend = mem.soff;
      msg("char pad%d[%d]\n", gap_cnt, gapend - gapstart);
      //msg("gap size=%a\n", gapend - gapstart);
      gapend = gapstart = BADADDR;
      gap_cnt++;
    }

    typeinfo_t mem_ti;
    retrieve_member_info(&mem, &mem_ti);

    // data type size of member
    asize_t dt_mem_size = get_data_type_size(mem.flag, &mem_ti);

    // member size
    asize_t mem_size = get_member_size(&mem);

    // get the member's name
    get_member_name(mem.id, buf, sizeof(buf));

    char dtype[MAXSTR];
    char arraystr[MAXSTR];
    char typemod[10];

    arraystr[0] = 0;
    typemod[0] = 0;

    if (isWord(mem.flag))
      strcpy(dtype, "unsigned short");
    else if (isDwrd(mem.flag))
      strcpy(dtype, "unsigned long");
    else if (isByte(mem.flag))
      strcpy(dtype, "char");
    else if (isStruct(mem.flag))
    {
      struc_t *nested_st = get_sptr(&mem);

      get_struc_name(nested_st->id, dtype, MAXSTR);
    }
    else 
      strcpy(dtype, "user_type");

    if (isOff0(mem.flag))
    {
      strcpy(typemod, "*");
    }

    if (isEnum0(mem.flag))
    {
      get_enum_name(mem_ti.ec.tid, dtype, sizeof(dtype));
    }

    asize_t ar_size = mem_size / dt_mem_size;

    // an array?
    if (ar_size > 1)
    {
      sprintf(arraystr, "[%d]", ar_size);
    }

    char out[100];
    sprintf(out, "%s " /* type */

                 "%s" /* typemodif */ "%s" /* varname */ "%s" /*array*/ ";", dtype, typemod, buf, arraystr);
    msg("%s\n", out);


/*
inline bool idaapi isByte  (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_BYTE; }
inline bool idaapi isWord  (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_WORD; }
inline bool idaapi isDwrd  (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_DWRD; }
inline bool idaapi isQwrd  (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_QWRD; }
inline bool idaapi isOwrd  (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_OWRD; }
inline bool idaapi isTbyt  (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_TBYT; }
inline bool idaapi isFloat (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_FLOAT; }
inline bool idaapi isDouble(flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_DOUBLE; }
inline bool idaapi isPackReal(flags_t F) { return isData(F) && (F & DT_TYPE) == FF_PACKREAL; }
inline bool idaapi isASCII (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_ASCI; }
inline bool idaapi isStruct(flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_STRU; }
inline bool idaapi is3byte (flags_t F)   { return isData(F) && (F & DT_TYPE) == FF_3BYTE; }

*/
    /*
    msg("member[%d], name=%s; %a-%a ; id=%d; flags=%x type=%s dt_mem_size=%a mem_size=%a\n", 
      i, 
      buf, 
      mem.soff, 
      mem.eoff, 
      mem.id, 
      mem.flag,
      type,
      dt_mem_size,
      mem_size);
    */
    // we expect next member to begin @ end of last member
    ofs = mem.eoff;
  }
}