diff --git a/include/Asm/arch.h b/include/Asm/arch.h index a3e0a69..c3b58d5 100644 --- a/include/Asm/arch.h +++ b/include/Asm/arch.h @@ -67,7 +67,6 @@ typedef uint32_t ArchOperand; # define AOF_SIGNED 0x4 /* for registers */ # define AOF_IMPLICIT 0x4 -# define AOF_OFFSETSIZE 0x8 /* macros */ # define AO_GET_FLAGS(operand) ((operand & AOM_FLAGS) >> AOD_FLAGS) @@ -77,11 +76,11 @@ typedef uint32_t ArchOperand; # define AO_GET_VALUE(operand) ((operand & AOM_VALUE) >> AOD_VALUE) # define AO_IMMEDIATE(flags, offset, size) ((AOT_IMMEDIATE << AOD_TYPE) \ - | (flags << AOD_FLAGS) | (offset << AOD_OFFSET) \ - | (size << AOD_SIZE)) + | ((flags) << AOD_FLAGS) | ((offset) << AOD_OFFSET) \ + | ((size) << AOD_SIZE)) # define AO_REGISTER(flags, offset, size, id) ((AOT_REGISTER << AOD_TYPE) \ - | (flags << AOD_FLAGS) | (offset << AOD_OFFSET) \ - | (size << AOD_SIZE) | (id << AOD_VALUE)) + | ((flags) << AOD_FLAGS) | ((offset) << AOD_OFFSET) \ + | ((size) << AOD_SIZE) | ((id) << AOD_VALUE)) # define AO_DREGISTER(flags, offset, dsize) ((AOT_DREGISTER << AOD_TYPE) \ | (flags << AOD_FLAGS) | (offset << AOD_OFFSET) \ | (dsize << AOD_SIZE)) @@ -114,7 +113,8 @@ struct _ArchPlugin ArchDescription * description; ArchRegister * registers; ArchInstruction * instructions; - int (*filter)(ArchPlugin * arch, ArchInstruction * instruction); + int (*filter)(ArchPlugin * arch, ArchInstruction * instruction, + unsigned char * buf, size_t size); }; #endif /* !DEVEL_ASM_ARCH_H */ diff --git a/src/arch.c b/src/arch.c index a896117..3b44c6a 100644 --- a/src/arch.c +++ b/src/arch.c @@ -166,6 +166,8 @@ ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size, static int _operands_operands(Arch * arch, ArchInstruction * ai, AsOperand ** operands, size_t operands_cnt); static int _operands_operands_immediate(uint32_t operand, AsOperand * aso); +static int _operands_operands_register(Arch * arch, uint32_t operand, + AsOperand * aso); ArchInstruction * arch_get_instruction_by_operands(Arch * arch, char const * name, AsOperand ** operands, size_t operands_cnt) @@ -197,7 +199,6 @@ static int _operands_operands(Arch * arch, ArchInstruction * ai, { size_t i; uint32_t operand; - ArchRegister * ar; for(i = 0; i < operands_cnt; i++) { @@ -219,27 +220,10 @@ static int _operands_operands(Arch * arch, ArchInstruction * ai, return -1; break; case AOT_DREGISTER: - /* check if it exists */ - ar = arch_get_register_by_name(arch, - operands[i]->value); - if(ar == NULL) - return -1; - /* FIXME implement the rest */ - break; case AOT_REGISTER: - /* check if it exists */ - ar = arch_get_register_by_name(arch, - operands[i]->value); - if(ar == NULL) + if(_operands_operands_register(arch, operand, + operands[i]) != 0) return -1; - /* for implicit instructions it must match */ - if(AO_GET_FLAGS(operand) & AOF_IMPLICIT) - { - if(AO_GET_SIZE(operand) != ar->size) - return -1; - if(AO_GET_VALUE(operand) != ar->id) - return -1; - } break; } } @@ -270,6 +254,30 @@ static int _operands_operands_immediate(uint32_t operand, AsOperand * aso) return 0; } +static int _operands_operands_register(Arch * arch, uint32_t operand, + AsOperand * aso) +{ + ArchRegister * ar; + ArchDescription * desc; + + /* check if it exists */ + ar = arch_get_register_by_name(arch, aso->value); + if(ar == NULL) + return -1; + /* check the size only for variable-length opcode encoding */ + desc = arch->plugin->description; + if((desc == NULL || desc->instruction_size == 0) + && AO_GET_SIZE(operand) != ar->size) + return -1; + /* for implicit instructions it must match */ + if(AO_GET_FLAGS(operand) & AOF_IMPLICIT) + { + if(AO_GET_VALUE(operand) != ar->id) + return -1; + } + return 0; +} + /* arch_get_name */ char const * arch_get_name(Arch * arch) @@ -312,3 +320,36 @@ ArchRegister * arch_get_register_by_name(Arch * arch, char const * name) return &arch->plugin->registers[i]; return NULL; } + + +/* arch_get_register_by_name_size */ +ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name, + uint32_t size) +{ + size_t i; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\", %u)\n", __func__, name, size); +#endif + for(i = 0; i < arch->registers_cnt; i++) + if(arch->plugin->registers[i].size != size) + continue; + else if(strcmp(arch->plugin->registers[i].name, name) == 0) + return &arch->plugin->registers[i]; + return NULL; +} + + +/* useful */ +/* arch_filter */ +int arch_filter(Arch * arch, ArchInstruction * instruction, unsigned char * buf, + size_t size) +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, instruction->name); +#endif + if(arch->plugin->filter == NULL) + return -error_set_code(1, "%s: %s", arch->plugin->name, + "Instruction filter required but not defined"); + return arch->plugin->filter(arch->plugin, instruction, buf, size); +} diff --git a/src/arch.h b/src/arch.h index a2fce60..21658ea 100644 --- a/src/arch.h +++ b/src/arch.h @@ -49,5 +49,11 @@ ArchInstruction * arch_get_instruction_by_operands(Arch * arch, ArchRegister * arch_get_register(Arch * arch, size_t index); ArchRegister * arch_get_register_by_id(Arch * arch, unsigned int id); ArchRegister * arch_get_register_by_name(Arch * arch, char const * name); +ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name, + uint32_t size); + +/* useful */ +int arch_filter(Arch * arch, ArchInstruction * ai, unsigned char * buf, + size_t size); #endif /* !ASM_ARCH_H */ diff --git a/src/arch/i386.c b/src/arch/i386.c index 17ce3ae..4f64ed3 100644 --- a/src/arch/i386.c +++ b/src/arch/i386.c @@ -16,6 +16,9 @@ #include +#ifdef DEBUG +# include +#endif #include "Asm/arch.h" @@ -57,6 +60,15 @@ static ArchInstruction _i386_instructions[] = #include "null.ins" }; + +/* prototypes */ +static int _i386_filter(ArchPlugin * plugin, ArchInstruction * instruction, + unsigned char * buf, size_t size); + + +/* public */ +/* variables */ +/* plug-in */ ArchPlugin arch_plugin = { "i386", @@ -64,5 +76,19 @@ ArchPlugin arch_plugin = NULL, _i386_registers, _i386_instructions, - NULL + _i386_filter }; + + + +/* functions */ +static int _i386_filter(ArchPlugin * plugin, ArchInstruction * instruction, + unsigned char * buf, size_t size) +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s() 0x%x\n", __func__, buf[0]); +#endif + /* the filter function is only set for mod r/m bytes at the moment */ + buf[0] |= 0xc0; + return 0; +} diff --git a/src/arch/i386.ins b/src/arch/i386.ins index f1452b3..715fa1f 100644 --- a/src/arch/i386.ins +++ b/src/arch/i386.ins @@ -14,8 +14,10 @@ /* helpers */ #define OP1F (8 << AOD_SIZE) #define OP2F (16 << AOD_SIZE) -#define OP_RM8 AO_DREGISTER(AOF_OFFSETSIZE, 8, 8) -#define OP_RMW AO_DREGISTER(AOF_OFFSETSIZE, 8, W) +#define OP_RM8_D AO_DREGISTER(AOF_SOFFSET, 8, 8) +#define OP_RM8_R AO_REGISTER(AOF_SOFFSET | AOF_FILTER, 8, 8, 0) +#define OP_RMW_D AO_DREGISTER(AOF_SOFFSET, 8, W) +#define OP_RMW_R AO_REGISTER(AOF_SOFFSET | AOF_FILTER, 8, W, 0) #define OP_U8 AO_IMMEDIATE(0, 0, 8) #define OP_UW AO_IMMEDIATE(0, 0, W) @@ -25,8 +27,10 @@ { "aam", 0xd40a, OP2F, AOT_NONE, AOT_NONE, AOT_NONE }, { "aam", 0xd4, OP1F, OP_U8, AOT_NONE, AOT_NONE }, { "aas", 0x3f, OP1F, AOT_NONE, AOT_NONE, AOT_NONE }, -{ "adc", 0x80, OP1F, OP_RM8, OP_U8, AOT_NONE }, -{ "adc", 0x81, OP1F, OP_RMW, OP_UW, AOT_NONE }, -{ "adc", 0x14, OP1F, OP_U8, OP_al, AOT_NONE }, -{ "adc", 0x15, OP1F, OP_UW, OP_AX, AOT_NONE }, +{ "adc", 0x14, OP1F, OP_al, OP_U8, AOT_NONE }, +{ "adc", 0x15, OP1F, OP_AX, OP_UW, AOT_NONE }, +{ "adc", 0x80, OP1F, OP_RM8_D, OP_U8, AOT_NONE }, +{ "adc", 0x80, OP1F, OP_RM8_R, OP_U8, AOT_NONE }, +{ "adc", 0x81, OP1F, OP_RMW_D, OP_UW, AOT_NONE }, +{ "adc", 0x81, OP1F, OP_RMW_R, OP_UW, AOT_NONE }, { "nop", 0x90, OP1F, AOT_NONE, AOT_NONE, AOT_NONE }, diff --git a/src/arch/sparc.c b/src/arch/sparc.c index f8e86c5..96873e7 100644 --- a/src/arch/sparc.c +++ b/src/arch/sparc.c @@ -22,7 +22,7 @@ /* sparc */ /* private */ /* variables */ -static ArchDescription _sparc_description = { ARCH_ENDIAN_BIG, 4, 4 }; +static ArchDescription _sparc_description = { ARCH_ENDIAN_BIG, 32, 32 }; #define REG(name, size, id) { "" # name, size, id }, static ArchRegister _sparc_registers[] = diff --git a/src/code.c b/src/code.c index 98b224a..b3ac2e3 100644 --- a/src/code.c +++ b/src/code.c @@ -42,6 +42,11 @@ struct _Code }; +/* prototypes */ +static int _code_filter(Code * code, ArchInstruction * ai, unsigned char * buf, + size_t size); + + /* functions */ /* code_new */ Code * code_new(char const * arch, char const * format) @@ -185,15 +190,15 @@ static int _instruction_fixed_register(Code * code, ArchOperand operand, AsOperand * aso, uint32_t * pu); static int _instruction_variable(Code * code, ArchInstruction * ai, AsOperand ** operands, size_t operands_cnt); -static int _instruction_variable_dregister(Code * code, ArchOperand operand, - char const * name); -static int _instruction_variable_immediate(Code * code, ArchOperand operand, - void * value, int swap); +static int _instruction_variable_dregister(Code * code, ArchInstruction * ai, + ArchOperand operand, char const * name); +static int _instruction_variable_immediate(Code * code, ArchInstruction * ai, + ArchOperand operand, void * value, int swap); static int _instruction_variable_opcode(Code * code, ArchInstruction * ai); -static int _instruction_variable_operand(Code * code, ArchOperand operand, - AsOperand * aso); -static int _instruction_variable_register(Code * code, ArchOperand operand, - char const * name); +static int _instruction_variable_operand(Code * code, ArchInstruction * ai, + ArchOperand operand, AsOperand * aso); +static int _instruction_variable_register(Code * code, ArchInstruction * ai, + ArchOperand operand, char const * name); int code_instruction(Code * code, char const * name, AsOperand ** operands, size_t operands_cnt) @@ -208,7 +213,7 @@ int code_instruction(Code * code, char const * name, AsOperand ** operands, ", 3 0x%x\n", name, ai->value, ai->op1, ai->op2, ai->op3); #endif - if(code->description != NULL && code->description->instruction_size) + if(code->description != NULL && code->description->instruction_size > 0) return _instruction_fixed(code, ai, operands, operands_cnt); return _instruction_variable(code, ai, operands, operands_cnt); } @@ -311,39 +316,42 @@ static int _instruction_variable(Code * code, ArchInstruction * ai, operand = ai->op3; else return -1; /* XXX report error */ - if(_instruction_variable_operand(code, operand, operands[i]) + if(_instruction_variable_operand(code, ai, operand, operands[i]) != 0) return -1; } return 0; } -static int _instruction_variable_dregister(Code * code, ArchOperand operand, - char const * name) +static int _instruction_variable_dregister(Code * code, ArchInstruction * ai, + ArchOperand operand, char const * name) { ArchRegister * ar; uint32_t value; - uint32_t offset; + uint32_t size; #ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, name); + fprintf(stderr, "DEBUG: %s(0x%08x, \"%s\")\n", __func__, operand, name); #endif - if((ar = arch_get_register_by_name(code->arch, name)) == NULL) + if(AO_GET_FLAGS(operand) & AOF_IMPLICIT) + return 0; + if((ar = arch_get_register_by_name_size(code->arch, name, AO_GET_SIZE( + operand))) == NULL) return -1; value = ar->id; - if(AO_GET_FLAGS(operand) & AOF_OFFSETSIZE) + if(AO_GET_FLAGS(operand) & AOF_SOFFSET) { - offset = AO_GET_OFFSET(operand); + size = AO_GET_OFFSET(operand); operand &= ~(AOM_OFFSET | AOM_SIZE); - operand |= (offset << AOD_SIZE); + operand |= (size << AOD_SIZE); } else value <<= AO_GET_OFFSET(operand); - return _instruction_variable_immediate(code, operand, &value, 0); + return _instruction_variable_immediate(code, ai, operand, &value, 0); } -static int _instruction_variable_immediate(Code * code, ArchOperand operand, - void * value, int swap) +static int _instruction_variable_immediate(Code * code, ArchInstruction * ai, + ArchOperand operand, void * value, int swap) { size_t size; void * buf; @@ -390,6 +398,8 @@ static int _instruction_variable_immediate(Code * code, ArchOperand operand, } else return -error_set_code(1, "%u: Size not implemented", size); + if(AO_GET_FLAGS(operand) & AOF_FILTER) + _code_filter(code, ai, buf, size); if(fwrite(buf, size, 1, code->fp) != 1) return -error_set_code(1, "%s: %s", code->filename, strerror( errno)); @@ -401,22 +411,27 @@ static int _instruction_variable_opcode(Code * code, ArchInstruction * ai) #ifdef DEBUG fprintf(stderr, "DEBUG: %s() 0x%x\n", __func__, ai->value); #endif - return _instruction_variable_immediate(code, ai->opcode, &ai->value, 1); + return _instruction_variable_immediate(code, ai, ai->opcode, &ai->value, + 1); } -static int _instruction_variable_operand(Code * code, ArchOperand operand, - AsOperand * aso) +static int _instruction_variable_operand(Code * code, ArchInstruction * ai, + ArchOperand operand, AsOperand * aso) { +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\", 0x%08x) opcode=0x%x\n", __func__, + ai->name, operand, ai->value); +#endif switch(AO_GET_TYPE(operand)) { case AOT_IMMEDIATE: - return _instruction_variable_immediate(code, operand, - aso->value, 1); + return _instruction_variable_immediate(code, ai, + operand, aso->value, 0); case AOT_DREGISTER: - return _instruction_variable_dregister(code, operand, - aso->value); + return _instruction_variable_dregister(code, ai, + operand, aso->value); case AOT_REGISTER: - return _instruction_variable_register(code, operand, + return _instruction_variable_register(code, ai, operand, aso->value); default: /* FIXME implement */ @@ -425,9 +440,15 @@ static int _instruction_variable_operand(Code * code, ArchOperand operand, return 0; } -static int _instruction_variable_register(Code * code, ArchOperand operand, - char const * name) +static int _instruction_variable_register(Code * code, ArchInstruction * ai, + ArchOperand operand, char const * name) { +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, name); +#endif + return _instruction_variable_dregister(code, ai, operand, name); +} +#if 0 ArchRegister * ar; uint32_t value; uint32_t offset; @@ -447,8 +468,9 @@ static int _instruction_variable_register(Code * code, ArchOperand operand, } else value <<= AO_GET_OFFSET(operand); - return _instruction_variable_immediate(code, operand, &value, 0); + return _instruction_variable_immediate(code, ai, operand, &value, 0); } +#endif #if 0 switch(AO_GET_SIZE(ai->opcode)) { @@ -635,3 +657,13 @@ int code_section(Code * code, char const * section) #endif return format_section(code->format, section); } + + +/* private */ +/* functions */ +/* plug-in */ +static int _code_filter(Code * code, ArchInstruction * ai, unsigned char * buf, + size_t size) +{ + return arch_filter(code->arch, ai, buf, size); +} diff --git a/test/i386.S b/test/i386.S index a2720db..f860918 100644 --- a/test/i386.S +++ b/test/i386.S @@ -5,10 +5,10 @@ aam aam $0x42 aas - adc $0x42, %al - adc $0x42, %eax + adc %al, $0x42 + adc %eax, $0x42 adc [%eax], $0x42 - adc [%ecx], $0x42 - adc [%eax], $0x42434445 - adc [%ecx], $0x42434445 + adc %ecx, $0x42 + adc [%edx], $0x42434445 + adc %ebx, $0x42434445 nop