天天看點

sizeof_function(函數代碼長度)

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; // 判斷函數長度有效性,傳回其得到的長度

}