/* Code generation functions. */ #include #include "inc/genCode.h" /* Generate a variable length size of code with optional jumps of a particular size. code: pre-allocated memory to place the code size: total size of the code to be generated (in bytes) Allocated size must be big enough to allocate a RET_BLOCK at the end jump: jump size in bytes (size of zero indicates a straight nop block) */ int generateCode( char * code, unsigned int size, unsigned int jump ) { unsigned int s, n, segments, nops; unsigned int sjmp, snop, sret; char *mem; /* compute size of code blocks from labels */ sjmp = &&endjmp-&&startjmp; snop = &&endnop-&&startnop; sret = &&endret-&&startret; /* compute number of segments to load according to the size of jumps */ if( jump ) { /* ensure jump is at least size of jump block */ if( jump < sjmp ) jump = sjmp; /* one segment per jump with as many nops as can fit between NOTE: the space between jumps may not fit an integral number of nops, there may be some space with garbage just prior to next jump block */ segments = size / jump; if( segments ) /* consider the return block as the start of the final segment */ segments--; nops = (jump - sjmp) / snop; } else { /* only one segment of enough nops to completely fill size */ segments = 1; nops = size / snop; } mem = code; /* create a number of segments */ for( s = 0; s < segments; s++ ) { /* set mem to start of segment */ mem = code + (s * jump); /* if using jumps add jump block and offset for start of nops */ if( jump ) { memcpy( mem, &&startjmp, sjmp ); mem += sjmp; } /* create a number of nop blocks */ for( n = 0; n < nops; n++ ) { memcpy( mem, &&startnop, snop ); mem += snop; } } /* copy return block */ memcpy( mem, &&startret, sret ); goto out; /* skip this code during run, used as templates for generated code */ JMP_BLOCK; NOP_BLOCK; RET_BLOCK; out: return( 0 ); } /* Return the size of a jump block when generated. return : size of jump block in bytes */ unsigned int jmpBlockSize( void ) { unsigned int sjmp = &&endjmp - &&startjmp; goto out; /* skip this code during run, used as template for sizing generated code */ JMP_BLOCK; out: return( sjmp ); } /* Return the size of a nop block when generated. return : size of nop block in bytesJMP */ unsigned int nopBlockSize( void ) { unsigned int snop = &&endnop - &&startnop; goto out; /* skip this code during run, used as template for sizing generated code */ NOP_BLOCK; out: return( snop ); } /* Return the size of a return block when generated. return : size of return block in bytes */ unsigned int retBlockSize( void ) { unsigned int sret = &&endret - &&startret; goto out; /* skip this code during run, used as template for sizing generated code */ RET_BLOCK; out: return( sret ); }