typedef struct _code_block
{
uint8_t* code; // 指令存放位置
ulong base; // 參考處理位址
size_t size; // 指令最大大小
} code_block;
size_t sizeof_function(code_block* block)
{
vector<uint8_t*> il; // 存放每條指令的位址
bool bresult = false;
uint8_t* ip = block->code; // 目前反彙編訓示符
uint8_t* far_ip = ip; // 辨別最遠的那條指令
size_t len = 0;
while ( len < block->size )
{
xde_instr instr;
uint8_t* next_ip;
// 如果反彙編失敗, 将導緻解析結束
if ( 0 == xde_disasm(ip, &instr) )
break;
len += instr.len;
il.push_back(ip); // 儲存目前 ip
next_ip = ip + instr.len; // 預設下一條指令
// 檢查目前指令是否是 jmp imm 類型的指令
// 如果是則重新計算目标位址。
if ( instr.opcode == 0xe9 ) // jmp imm32
{
next_ip += instr.data_l[0];
}
else if ( instr.flag & C_REL ) // 如果是相對跳轉
{
if ( instr.len == 2 ) // jxx imm8 or loop imm8
next_ip += instr.data_c[0];
else if ( instr.len == 6 )
next_ip += instr.data_l[0];
}
// 檢查下條指令是否超出範圍
if ( next_ip <= block->code || next_ip >= block->code + block->size )
break;
// 如果下一條指令是往回跳,則檢查其目的位址有效性
if ( next_ip >= block->code && next_ip <= ip )
{
if ( find(il.begin(), il.end(), far_ip) == il.end() )
break;
}
// 檢查最遠的那條指令是否已經處理過
if ( ip + instr.len > far_ip )
{
if ( find(il.begin(), il.end(), far_ip) == il.end() ) // 出現花指令
break;
}
// 檢測目前指令是否是最遠的指令,而且目前這條指令是傳回指令
if ( far_ip == ip && (instr.flag & C_STOP) )
{
bresult = true;
break;
}
// 檢查最遠的那條指令是否還是最遠
if ( next_ip > far_ip )
far_ip = next_ip; // 更新最遠的位址
ip += instr.len; // 順序性的下條指令
}
return bresult ? len : 0; // 判斷函數長度有效性,傳回其得到的長度
}