Skip to content
Snippets Groups Projects
ProfilerInformation.cpp 5.06 KiB

#include <cstdlib>

#include "ProfilerInformation.h"


#define qfeof feof

/*
 * ascii-to-longlong conversion; Visual Studio 2005 lacks atoll() library func
 *
 * no error checking; assumes decimal digits
 *
 * efficient conversion: 
 *   start with value = 0
 *   then, starting at first character, repeat the following
 *   until the end of the string:
 *
 *     new value = (10 * (old value)) + decimal value of next character
 *
 */

long long my_atoll(char *instr) {
	long long retval = 0;

	for (; *instr; ++instr) {
		retval = 10*retval + (*instr - '0');
	}
	return retval;
}

#ifdef WIN32
#define atoll my_atoll
#endif

ProfilerInformation::ProfilerInformation(const char* fn)
	: filename(std::string(fn))
{

	FILE* fin;
	int addr;
	union {int size, type;} size_type_u;
	char type[200];
	char scope[200];
	char remainder[2000];
	int line=0;

	if (fn[0]==0)
		return;

	fin = qfopen(fn, "r");

	if (!fin)
	{
		msg("Cannot open strata annotation file %s\n", fn);
		return;
	}



	do 
	{
		qfscanf(fin, "%x %d\n", &addr, &size_type_u);

		if (qfeof(fin))		// deal with blank lines at the EOF
			break;
		
		qfscanf(fin, "%s%s", type,scope);

		/* if the size > 0, then this is a declaration of a variable */
		if (strcmp(type,"FUNC") == 0)
		{
			; // no useful info for the SA.
			
		}
		else if (strcmp(type,"MEMORYHOLE") == 0)
		{
			// no useful info for the SA.
		}
		else if (strcmp(type,"INSTR") == 0)
		{
			// no useful info for the SA.
		}
		else if (strcmp(type,"PTRIMMEDEBP")==0 || 
			strcmp(type,"PTRIMMEDESP")==0 || 
			strcmp(type,"PTRIMMEDESP2")==0 || 
			strcmp(type,"PTRIMMEDABSOLUTE")==0
		       )
		{
                        int the_const;
                        int real_const=0;
			char field[100];
			assert(strcmp(scope,"STACK") == 0 || strcmp(scope,"GLOBAL") == 0);

			/* remaining params are <const> <field> <real_const_if_global> <comment> */ 
			qfscanf(fin, "%d %s", &the_const, field);
			if (strcmp(type,"PTRIMMEDESP2") == 0 || 
				strcmp(type,"PTRIMMEDABSOLUTE") == 0)
				qfscanf(fin, "%x", &real_const);
			else
				real_const=the_const;

			// successfully read in, but, ignoring for now.
			if (strcmp(type,"PTRIMMEDESP2")==0 || strcmp(type,"PTRIMMEDABSOLUTE")==0 )
			{
				profileAddressingInformation(addr,size_type_u.size,type, scope,the_const,field,real_const);
			}
			
		}
		else if (strcmp(type,"DATAREF")==0)
		{
			// no useful info for the SA.

		}
		else if (strcmp(type,"DEALLOC")==0)
		{
			// no useful info for the SA.
			assert(strcmp(scope,"STACK")==0);
			/* remaining params: comment */
		}
		else if (strcmp(type,"PROFILEDNUMERIC")==0)
		{
			/* profiler generated information */
			addProfileInformation(addr,atoll(scope),0,0);
		}
		else if (strcmp(type,"PROFILEDPOINTER")==0 )
		{
			/* profiler generated information */
			addProfileInformation(addr,0,atoll(scope),0);
		}
		else if (strcmp(type,"PROFILEDOTHER")==0 )
		{
			/* profiler generated information */
			addProfileInformation(addr,0,0,atoll(scope));
		}
		else
		{
			assert(0);
		}
	
		qfgets(remainder, sizeof(remainder), fin);
		line++;
	} while (!qfeof(fin));
	qfclose(fin);

	msg("Successfully loaded annotation file %s\n", fn);
}

ProfilerInformation::~ProfilerInformation() {
	FILE* fout = qfopen(filename.c_str(), "a+");
	
	if (!fout) {
		msg("Cannot open annotations file (%s) for output\n", filename.c_str());		
		assert(fout);
	}

	for (std::set<std::string>::iterator iter=constant_info.begin();
		iter != constant_info.end();
		++iter
	   )
	{
		qfprintf(fout, "%s", (*iter).c_str());
	}

	for (std::map<ea_t,InstructionInformation*>::iterator iter = the_map.begin();
		iter != the_map.end();
		++iter
	   )
	{
		ea_t addr=(*iter).first;
		InstructionInformation *ii=(*iter).second;
		if (ii)
		{

			if (ii->getNumericCount())
			{
				qfprintf(fout, "%x %d %s %d Profiler generated, summarized by idal\n",
					addr, 0, "PROFILEDNUMERIC", ii->getNumericCount());
			}
			if (ii->getPointerCount())
			{
				qfprintf(fout, "%x %d %s %d Profiler generated, summarized by idal\n",
					addr, 0, "PROFILEDPOINTER", ii->getPointerCount());
			}
			if (ii->getOtherCount())
			{
				qfprintf(fout, "%x %d %s %d Profiler generated, summarized by idal\n",
					addr, 0, "PROFILEDOTHER", ii->getOtherCount());
			}
			delete ii;
		}
	}

	qfclose(fout);

}

void ProfilerInformation::addProfileInformation(ea_t addr, long long nc, long long pc, long long oc) {
	InstructionInformation *ii = GetInfo(addr);

	if (!ii) {
		ii = new InstructionInformation;
		SetInfo(addr, ii);
	}

	if (nc)
		ii->setNumericCount((int) nc);
	if (pc)
		ii->setPointerCount((int) pc);
	if (oc)
		ii->setOtherCount((int) oc);

//	msg("Profiled %x to be nc:%lld pc:%lld oc:%lld\n", addr,
//		ii->getNumericCount(),
//		ii->getPointerCount(),
//		ii->getOtherCount());

	return;
}

void ProfilerInformation::profileAddressingInformation
	(
		ea_t addr,
		int size,
		char *type,
		char *scope, 
		ea_t the_const,
		char* field, 
		ea_t real_const
	)
{
	char buffer[1000];
	qsnprintf(buffer, sizeof(buffer), "%x %d %s %s %d %s %x Profiler generated, idal summarized\n", 
		addr, size, type, scope,the_const,field,real_const); 
	constant_info.insert(std::string(buffer));
}