So anyway, first of all you need to modify the x86 Decoder a bit. And you need to be able to resolve jmp instructions for this to work in debug builds.
void* GetActualStartOfFunction( void* );
int NicksModifiedFunction( void*, unsigned char* );
struct SomeStruct
{
SomeStruct() // we'll get the address of this ctor.
:i_(3)
{}
int i_;
};
// You need a function that will create the object you want the address of the
// constructor of.
void CreateSomeStruct()
{
SomeStruct ss;
}
void* GetAddrOfCtor( void (*creator_func)() )
{
void* paddr = GetActualStartOfFunction((unsigned char*)creator_func);
unsigned char* instr = (unsigned char*)paddr;
while(1) // probably better put a limit on this...
{
int sz = NicksModifiedFunction(instr, 0);
if( *instr == 0xE8 ) // the call instruction (should probably check for other versions of it)
{
paddr = (void*)(int(instr + sz) + *((int*)(instr + 1)));
break;
}
instr += sz;
}
return paddr;
}
void main()
{
void* addr = GetAddrOfCtor(CreateSomeStruct);
}
Next I present the modified x86 decoder, which now calculates the size of a single instruction and returns the actual opcode, and the GetActualAddrOfFunction which resolves the jmp instruction (in vc++7 builds at least) to get the actual address of a function.
void* GetActualAddrOfFunction( void* p )
{
void* actual = p;
unsigned char code = 0;
int sz = NicksModifiedFunction( (unsigned char*)p, &code );
switch( code )
{
case 0xeb: // Jump short, relative, displacement relative to next instruction
// 8 bit
break;
case 0xe9: // Jump near, relative, displacement relative to next instruction
// 32 or 16 bit.
return (void*)(*(unsigned int*)instr + (unsigned int)p + sz);
break;
case 0xff: // Jump far, absolute indirect, address given in r/m16/32:16/32
// Jump near, absolute indirect, address given in m16/32:16/32
break;
case 0xea: // Jump far, absolute, address given in operand
// 32 or 16 bit
break;
}
return actual;
}
int NicksModifiedFunction( void* instr, unsigned char* outCode )
{
unsigned char* func = (unsigned char*)instr;
int total = 0;
int operandSize = 4;
int FPU = 0;
while(*func == 0xF0 || *func == 0xF2 || *func == 0xF3 || (*func & 0xFC) == 0x64 ||
(*func & 0xF8) == 0xD8 || (*func & 0x7E) == 0x62)
{
if(*func == 0x66)
operandSize = 2;
else if((*func & 0xF8) == 0xD8)
{
FPU = *func++; total++;
break;
}
func++; total++;
}
bool twoByte = false;
if(*func == 0x0F)
{
twoByte = true;
func++; total++;
}
unsigned char opcode = *func++; total++;
unsigned char modRM = 0xFF;
if(FPU)
{
if((opcode & 0xC0) != 0xC0)
modRM = opcode;
}
else if(!twoByte)
{
if((opcode & 0xC4) == 0x00 || (opcode & 0xF4) == 0x60 && ((opcode & 0x0A) == 0x02 ||
(opcode & 0x09) == 0x9) ||
(opcode & 0xF0) == 0x80 || (opcode & 0xF8) == 0xC0 && (opcode & 0x0E) != 0x02 ||
(opcode & 0xFC) == 0xD0 || (opcode & 0xF6) == 0xF6)
{
modRM = *func++; total++;
}
}
else
{
if((opcode & 0xF0) == 0x00 && (opcode & 0x0F) >= 0x04 && (opcode & 0x0D) != 0x0D ||
(opcode & 0xF0) == 0x30 || opcode == 0x77 || (opcode & 0xF0) == 0x80 ||
(opcode & 0xF0) == 0xA0 && (opcode & 0x07) <= 0x02 || (opcode & 0xF8) == 0xC8)
{
// No mod R/M byte
}
else
{
modRM = *func++; total++;
}
}
// Skip SIB
if((modRM & 0x07) == 0x04 &&
(modRM & 0xC0) != 0xC0)
{
func += 1; total += 1;
}
// Skip displacement
if((modRM & 0xC5) == 0x05) {func += 4;total+=4;} // Dword displacement, no base
if((modRM & 0xC0) == 0x40) {func += 1;total+=1;} // Byte displacement
if((modRM & 0xC0) == 0x80) {func += 4;total+=4;} // Dword displacement
// Skip immediate
if(FPU)
{
// Can't have immediate operand
}
else if(!twoByte)
{
if((opcode & 0xC7) == 0x04 || (opcode & 0xFE) == 0x6A || (opcode & 0xF0) == 0x70 || // Jcc
opcode == 0x80 || opcode == 0x83 || (opcode & 0xFD) == 0xA0 || // MOV
opcode == 0xA8 || (opcode & 0xF8) == 0xB0 || (opcode & 0xFE) == 0xC0 ||
opcode == 0xC6 || opcode == 0xCD || (opcode & 0xFE) == 0xD4 || // AAD/AAM
(opcode & 0xF8) == 0xE0 || opcode == 0xEB || opcode == 0xF6 && (modRM & 0x30) == 0x00) // TEST
{
func += 1; total += 1;
}
else if((opcode & 0xF7) == 0xC2)
{
func += 2; total += 2; // RET
}
else if((opcode & 0xFC) == 0x80 || (opcode & 0xC7) == 0x05 || (opcode & 0xF8) == 0xB8 ||
(opcode & 0xFE) == 0xE8 || (opcode & 0xFE) == 0x68 || (opcode & 0xFC) == 0xA0 ||
(opcode & 0xEE) == 0xA8 || opcode == 0xC7 || opcode == 0xF7 && (modRM & 0x30) == 0x00)
{
func += operandSize; total += operandSize;
}
}
else
{
if(opcode == 0xBA || opcode == 0x0F || (opcode & 0xFC) == 0x70 || // PSLLW
(opcode & 0xF7) == 0xA4 || opcode == 0xC2 || opcode == 0xC4 ||
opcode == 0xC5 || opcode == 0xC6)
{
func += 1; total += 1;
}
else if((opcode & 0xF0) == 0x80)
{
func += operandSize; total += operandSize; // Jcc -i
}
}
if( outCode ) *outCode = opcode;
return total;
}













