xenoborg/alpha/source/x86/include/emu/emu_cpu_data.h
blueshogun96@gmail.com e140504ee8
2012-01-05 00:09:50 +00:00

286 lines
9 KiB
C

/********************************************************************************
* libemu
*
* - x86 shellcode emulation -
*
*
* Copyright (C) 2007 Paul Baecher & Markus Koetter
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
* contact nepenthesdev@users.sourceforge.net
*
*******************************************************************************/
#ifndef EMU_CPU_DATA_H_
#define EMU_CPU_DATA_H_
#include <stdint.h>
#include <stdbool.h>
#include <emu/emu.h>
#include <emu/emu_cpu_instruction.h>
#include <emu/emu_instruction.h>
enum emu_cpu_flag {
f_cf = 0, f_pf = 2, f_af = 4, f_zf = 6, f_sf = 7, f_tf = 8, f_if = 9,
f_df = 10, f_of = 11
};
#define CPU_FLAG_SET(cpu_p, fl) (cpu_p)->eflags |= 1 << (fl)
#define CPU_FLAG_UNSET(cpu_p, fl) (cpu_p)->eflags &= ~(1 << (fl))
#define CPU_FLAG_TOGGLE(cpu_p, fl) (cpu_p)->eflags ^= 1 << (fl)
#define CPU_FLAG_ISSET(cpu_p, fl) ((cpu_p)->eflags & (1 << (fl)))
struct emu_track_and_source;
struct emu_cpu
{
struct emu *emu;
struct emu_memory *mem;
uint32_t eip;
uint32_t eflags;
uint32_t reg[8];
uint16_t *reg16[8];
uint8_t *reg8[8];
struct emu_instruction instr;
struct emu_cpu_instruction_info *cpu_instr_info;
uint32_t last_fpu_instr[2];
char *instr_string;
bool repeat_current_instr;
struct emu_track_and_source *tracking;
};
#define MODRM_MOD(x) (((x) >> 6) & 3)
#define MODRM_REGOPC(x) (((x) >> 3) & 7)
#define MODRM_RM(x) ((x) & 7)
#define SIB_SCALE(x) (((x) >> 6) & 3)
#define SIB_INDEX(x) (((x) >> 3) & 7)
#define SIB_BASE(x) ((x) & 7)
#define PREFIX_ADSIZE (1 << 0)
#define PREFIX_OPSIZE (1 << 1)
#define PREFIX_LOCK (1 << 2)
#define PREFIX_CS_OVR (1 << 3)
#define PREFIX_DS_OVR (1 << 4)
#define PREFIX_ES_OVR (1 << 5)
#define PREFIX_FS_OVR (1 << 6)
#define PREFIX_GS_OVR (1 << 7)
#define PREFIX_SS_OVR (1 << 8)
#define PREFIX_F2 (1 << 9)
#define PREFIX_F3 (1 << 10)
#define OPSIZE_8 1
#define OPSIZE_16 2
#define OPSIZE_32 3
#define MAX_INT8 127
#define MIN_INT8 -128
#define MAX_UINT8 255
#define MIN_UINT8 0
#define MAX_INT16 32767
#define MIN_INT16 -MAX_INT16 -1
#define MAX_UINT16 65535
#define MIN_UINT16 0
#define MAX_INT32 2147483647
#define MIN_INT32 -MAX_INT32 -1
#define MAX_UINT32 4294967295U
#define MIN_UINT32 0
extern int64_t max_inttype_borders[][2][2];
#define INTOF(bits) int##bits##_t
#define UINTOF(bits) uint##bits##_t
#if !defined(INSTR_CALC)
#if BYTE_ORDER == BIG_ENDIAN
#define INSTR_CALC(bits, a, b, c, operation) \
UINTOF(bits) operand_a; \
UINTOF(bits) operand_b; \
bcopy(&(a), &operand_a, bits/8); \
bcopy(&(b), &operand_b, bits/8); \
UINTOF(bits) operation_result = operand_a operation operand_b; \
bcopy(&operation_result, &(c), bits/8);
#else // ENDIAN
#define INSTR_CALC(bits, a, b, c, operation) \
UINTOF(bits) operand_a = a; \
UINTOF(bits) operand_b = b; \
UINTOF(bits) operation_result = operand_a operation operand_b; \
c = operation_result;
#endif // ENDIAN
#endif // INSTR_CALC
#if !defined(INSTR_SET_FLAG_ZF)
#define INSTR_SET_FLAG_ZF(cpu) \
{ \
if (operation_result == 0) \
CPU_FLAG_SET(cpu, f_zf); \
else \
CPU_FLAG_UNSET(cpu, f_zf); \
}
#endif // INSTR_SET_FLAG_ZF
#if !defined(INSTR_SET_FLAG_PF)
#define INSTR_SET_FLAG_PF(cpu) \
{ \
int num_p_bits=0; \
int i; \
for ( i=0;i<8;i++ ) \
if (operation_result & (1 << i) ) \
num_p_bits++; \
\
if ((num_p_bits % 2) == 0) \
CPU_FLAG_SET(cpu, f_pf); \
else \
CPU_FLAG_UNSET(cpu, f_pf); \
}
#endif // INSTR_SET_FLAG_PF
#if !defined(INSTR_SET_FLAG_SF)
#define INSTR_SET_FLAG_SF(cpu) \
{ \
if (operation_result & (1 << (sizeof(operation_result)*8 - 1))) \
CPU_FLAG_SET(cpu, f_sf); \
else \
CPU_FLAG_UNSET(cpu, f_sf); \
}
#endif // INSTR_SET_FLAG_SF
#if !defined(INSTR_SET_FLAG_OF)
#define INSTR_SET_FLAG_OF(cpu, operand, bits) \
{ \
int64_t sx = (INTOF(bits))operand_a; \
int64_t sy = (INTOF(bits))operand_b; \
int64_t sz = 0; \
\
sz = sx operand sy; \
\
if (sz < max_inttype_borders[sizeof(operation_result)][0][0] || sz > max_inttype_borders[sizeof(operation_result)][0][1] \
|| sz != (INTOF(bits))operation_result ) \
{ \
CPU_FLAG_SET(cpu, f_of); \
}else \
{ \
CPU_FLAG_UNSET(cpu, f_of); \
} \
}
#endif // INSTR_SET_FLAG_OF
#if !defined(INSTR_SET_FLAG_CF)
#define INSTR_SET_FLAG_CF(cpu, operand) \
{ \
uint64_t ux = (uint64_t)operand_a; \
uint64_t uy = (uint64_t)operand_b; \
uint64_t uz = 0; \
\
uz = ux operand uy; \
\
if (uz < max_inttype_borders[sizeof(operation_result)][1][0] || uz > max_inttype_borders[sizeof(operation_result)][1][1] \
|| uz != (uint64_t)operation_result ) \
{ \
CPU_FLAG_SET(cpu, f_cf); \
}else \
{ \
CPU_FLAG_UNSET(cpu, f_cf); \
} \
}
#endif // INSTR_SET_FLAG_CF
#include <string.h>
#define WORD_UPPER_TO_BYTE(to,from) \
memcpy(&(to),((uint8_t *)&(from))+1,1);
#define WORD_LOWER_TO_BYTE(to,from) \
memcpy(&(to),&(from),1);
#define DWORD_UPPER_TO_WORD(to,from) \
memcpy(&(to),((uint8_t *)&(from))+2,2);
#define DWORD_LOWER_TO_WORD(to,from) \
memcpy(&(to),&(from),2);
#define QWORD_UPPER_TO_DWORD(to,from) \
memcpy(&(to),((uint8_t *)&(from))+4,4);
#define QWORD_LOWER_TO_DWORD(to,from) \
memcpy(&(to),&(from),4);
#define DWORD_FROM_WORDS(to, upper, lower) \
memcpy(&to,&lower,2); \
memcpy(((char *)&to)+2,&lower,2);
#define QWORD_FROM_DWORDS(to, upper, lower) \
memcpy(&to,&lower,4); \
memcpy(((char *)&to)+4,&lower,4);
#define TRACK_INIT_REG32(instruction, reg32) (instruction).track.init.reg[reg32] = 0xffffffff;
#define TRACK_NEED_REG32(instruction, reg32) (instruction).track.need.reg[reg32] = 0xffffffff;
#define TRACK_INIT_REG16(instruction, reg16) (instruction).track.init.reg[reg16] |= 0xffff << 16;
#define TRACK_NEED_REG16(instruction, reg16) (instruction).track.need.reg[reg16] |= 0xffff << 16;
#define TRACK_INIT_REG8(instruction, reg8) (instruction).track.init.reg[reg8] |= 0xff << 24;
#define TRACK_NEED_REG8(instruction, reg8) (instruction).track.need.reg[reg8] |= 0xff << 24;
#define TRACK_INIT_EFLAG(instruction, fl) (instruction).track.init.eflags |= 1 << (fl)
#define TRACK_NEED_EFLAG(instruction, fl) (instruction).track.need.eflags |= 1 << (fl)
#define SOURCE_NORM_POS(instruction, pos) (instruction).source.norm_pos = pos;
#define SOURCE_COND_POS(instruction, pos) (instruction).source.has_cond_pos = 1; (instruction).source.cond_pos = pos;
#define TRACK_FPU_LAST_INSTRUCTION 0x0
#define TRACK_INIT_FPU(instruction, what) (instruction).track.init.fpu |= 1 << (what);
#define TRACK_NEED_FPU(instruction, what) (instruction).track.need.fpu |= 1 << (what);
#define NNY "no need yet"
#define SST "16bit memory access is unsupported"
#define UNIMPLEMENTED(cpu_p, reason) \
emu_strerror_set((cpu_p)->emu, "The following function is unimplemented %s %s:%i (%s)", __PRETTY_FUNCTION__, __FILE__, __LINE__, reason); \
return -1;
#define STUB(cpu_p) \
emu_log((cpu_p)->emu, EMU_LOG_INFO, "The following function is a stub %s %s:%i \n", __PRETTY_FUNCTION__, __FILE__, __LINE__);
#endif /*EMU_CPU_DATA_H_*/