#include bastard


/* --------------------------------------------------------------------------
   Post-Disassembly Pass 1 : Subroutine Recognition 

	Queries the disassembler library for code sequences that identify
	function prologues and epilogues [entry and exit], then walks through
	the CODE table, creating FUNCTION objects for portions of the target
	that are contained in a prologue/epilogue block.

	Also, the first 'reference implementation' of a pass ;)
*/

int test_pattern(code_t *input, code_t *pattern){
	code_t c, *d;
	int cont = 1, x = 0;

	d = &pattern[x];
	/* this is redundant but needed to set ADDR index */
	DBIndexFind(CODE_RVA, &input->rva, &c);
	while ( d->mnemonic[0] && cont ){
		if ( strcmp(d->mnemonic, c.mnemonic)) return(0);
		if ( d->dest && strcmp(d->dest, c.dest)) return(0);
		if ( d->src && strcmp(d->src, c.src)) return(0);
		if ( d->aux && strcmp(d->aux, c.aux)) return(0);
		if (! DBIndexNext(CODE_RVA, &c)) cont = 0;
		d = &pattern[++x];
	}
	return(1);
}

int make_subroutine( code_t *input) {
	code_t c, *table;
	char name[16];
	int i, num, ok, size = 0;
	
	num = DisEpilogue( &table );
	ok = DBIndexFind(CODE_RVA, &input->rva, &c);
	/* search for subroutine end */
	/* TODO: we may want to improve this to follow jmps and such */
	while (ok) {
		ok = DBIndexNext(CODE_RVA, &c);
		for ( i = 0; i < num; i++ ){
			if (test_pattern(&c, &table[i])) {
				ok = 0;
				size = c.rva - input->rva;
			}
			while( (table[i]).mnemonic[0] )
				i++;
		}
	}
	if ( ! size ) return(0); /* there is a problem, houston */
	
	/* check if existing subroutine in DB */
	ok = GetFuncEnd(input->rva);
	if (! ok) {
		/* add function */
		sprintf(name, "sub_%X", input->rva);
		SetName( input->rva, name, NAME_AUTO);
		DefineFunc(input->rva, name, size);
	} else if ( ok  < input->rva + size){
		/* resize function */
		SetFuncSize(input->rva, size);
	} 
		
	return(1);
}

/*  -------------------------------------------------------------------main()
*/
int main()
{
	int i, j, num, ok;
	code_t *table, c;
	
	Message("Detecting Subroutines\n");

	num = DisPrologue( &table );
	for ( i = 0, j = 0; j < num; i++, j++){
		/* foreach keyfind(pattern.mnemonic) */
		ok = DBIndexFind(MNEMONIC, (table[i]).mnemonic, &c);
		while (ok) {
			if ( test_pattern( &c, &table[i]) ) {
				make_subroutine( &c );
			}
			DBIndexNext(MNEMONIC, &c);
			/* end of matches for this mnemonic */
			if (strcmp(c.mnemonic, (table[i]).mnemonic)) ok = 0;
		}

		/* skip to end of pattern */
		while( (table[i]).mnemonic[0] ){
			i++;
		}
	}
	
	return(0);
}
