diff --git a/include/Asm.h b/include/Asm.h index 9f9ad4a..bcb356e 100644 --- a/include/Asm.h +++ b/include/Asm.h @@ -18,8 +18,47 @@ #ifndef DEVEL_ASM_H # define DEVEL_ASM_H +# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +# include +# elif defined(__linux__) +# include +# endif + # include "Asm/arch.h" # include "Asm/asm.h" # include "Asm/format.h" + +/* helpers */ +# if _BYTE_ORDER == _BIG_ENDIAN +# define _htob16(a) (a) +# define _htol16(a) (((a) & 0xff) << 8 | ((a) & 0xff00) >> 8) +# define _htob32(a) (a) +# define _htol32(a) (((a) & 0xff) << 24 | (((a) & 0xff00) << 8) \ + | (((a) & 0xff0000) >> 8) | ((a) & 0xff000000) >> 24) +# define _htob64(a) (a) +# define _htol64(a) (((a) & 0xff) << 56) | (((a) & 0xff00) << 40) \ + | (((a) & 0xff0000) << 24) | (((a) & 0xff000000) << 8) \ + | (((a) & 0xff00000000) >> 8) \ + | (((a) & 0xff0000000000) >> 24) \ + | (((a) & 0xff000000000000) >> 40) \ + | (((a) & 0xff00000000000000) >> 56) +# elif _BYTE_ORDER == _LITTLE_ENDIAN +# define _htob16(a) (((a) & 0xff) << 8 | ((a) & 0xff00) >> 8) +# define _htol16(a) (a) +# define _htob32(a) (((a) & 0xff) << 24 | (((a) & 0xff00) << 8) \ + | (((a) & 0xff0000) >> 8) | ((a) & 0xff000000) >> 24) +# define _htol32(a) (a) +# define _htob64(a) (((a) & 0xff) << 56) | (((a) & 0xff00) << 40) \ + | (((a) & 0xff0000) << 24) | (((a) & 0xff000000) << 8) \ + | (((a) & 0xff00000000) >> 8) \ + | (((a) & 0xff0000000000) >> 24) \ + | (((a) & 0xff000000000000) >> 40) \ + | (((a) & 0xff00000000000000) >> 56) +# define _htol64(a) (a) +# else +# warning "Could not determine endian on your system" +# endif + + #endif /* !DEVEL_ASM_H */ diff --git a/include/Asm/arch.h b/include/Asm/arch.h index e337df3..5ae05f4 100644 --- a/include/Asm/arch.h +++ b/include/Asm/arch.h @@ -19,9 +19,10 @@ # define DEVEL_ASM_ARCH_H # include +# include -/* AsArch */ +/* AsmArch */ /* types */ typedef enum _ArchEndian { @@ -32,19 +33,22 @@ typedef enum _ArchEndian typedef struct _ArchDescription { + char const * format; /* default format */ ArchEndian endian; uint32_t alignment; uint32_t instruction_size; /* 0 if not constant */ } ArchDescription; /* operands */ -typedef uint32_t ArchOperand; -# define AOT_NONE 0x0 -# define AOT_CONSTANT 0x1 /* flags | 0 | size | value */ -# define AOT_IMMEDIATE 0x2 /* flags | offset | 0 | size */ -# define AOT_REGISTER 0x3 /* flags | 0 | size | id */ -# define AOT_DREGISTER 0x4 /* flags | dsize | rsize | id */ -# define AOT_DREGISTER2 0x5 /* flags | did | rsize | id */ +typedef enum _ArchOperandType +{ + AOT_NONE = 0x0, + AOT_CONSTANT = 0x1, /* flags | 0 | size | value */ + AOT_IMMEDIATE = 0x2, /* flags | offset | 0 | size */ + AOT_REGISTER = 0x3, /* flags | 0 | size | id */ + AOT_DREGISTER = 0x4, /* flags | dsize | rsize | id */ + AOT_DREGISTER2 = 0x5 /* flags | did | rsize | id */ +} ArchOperandType; /* displacement */ # define AOD_FLAGS 24 @@ -62,11 +66,10 @@ typedef uint32_t ArchOperand; /* flags */ # define AOF_FILTER 0x1 -# define AOF_SOFFSET 0x2 /* for immediate */ -# define AOF_SIGNED 0x4 +# define AOF_SIGNED 0x2 /* for registers */ -# define AOF_IMPLICIT 0x4 +# define AOF_IMPLICIT 0x2 /* macros */ # define AO_GET_FLAGS(operand) ((operand & AOM_FLAGS) >> AOD_FLAGS) @@ -100,16 +103,60 @@ typedef uint32_t ArchOperand; | ((dsize) << AOD_SIZE) \ | ((id) << AOD_VALUE)) +typedef struct _ArchOperand +{ + ArchOperandType type; + union + { + /* AOT_DREGISTER */ + struct + { + char * name; + int64_t offset; + } dregister; + + /* AOT_DREGISTER2 */ + struct + { + char * name; + char * name2; + } dregister2; + + /* AOT_IMMEDIATE */ + struct + { + uint64_t value; + int negative; + } immediate; + + /* AOT_REGISTER */ + struct + { + char * name; + } _register; + /* FIXME complete */ + } value; +} ArchOperand; + +typedef uint32_t ArchOperandDefinition; + typedef struct _ArchInstruction { char * name; - uint32_t value; - ArchOperand opcode; - ArchOperand op1; - ArchOperand op2; - ArchOperand op3; + uint32_t opcode; + ArchOperandDefinition flags; + ArchOperandDefinition op1; + ArchOperandDefinition op2; + ArchOperandDefinition op3; } ArchInstruction; +typedef struct _ArchInstructionCall +{ + char * name; + ArchOperand operands[3]; + size_t operands_cnt; +} ArchInstructionCall; + typedef struct _ArchRegister { char * name; @@ -117,17 +164,29 @@ typedef struct _ArchRegister uint32_t id; } ArchRegister; +typedef struct _ArchPluginHelper +{ + char const * filename; + FILE * fp; + void * priv; +} ArchPluginHelper; + typedef struct _ArchPlugin ArchPlugin; struct _ArchPlugin { + ArchPluginHelper * helper; + char const * name; - char const * format; /* default format */ + ArchDescription * description; ArchRegister * registers; ArchInstruction * instructions; - int (*filter)(ArchPlugin * arch, ArchInstruction * instruction, - ArchOperand operand, unsigned char * buf, size_t size); + + int (*write)(ArchPlugin * arch, ArchInstruction * instruction, + ArchInstructionCall * call); + /* FIXME complete and implement */ + int (*read)(ArchPlugin * arch); }; #endif /* !DEVEL_ASM_ARCH_H */ diff --git a/include/Asm/asm.h b/include/Asm/asm.h index 00c7f4c..575e835 100644 --- a/include/Asm/asm.h +++ b/include/Asm/asm.h @@ -26,15 +26,6 @@ /* types */ typedef struct _As As; -typedef struct _AsOperand -{ - ArchOperand operand; - /* FIXME should be a union */ - int dereference; - void * value; - void * value2; -} AsOperand; - typedef enum _AsPluginType { ASPT_ARCH = 0, ASPT_FORMAT } AsPluginType; diff --git a/include/Asm/format.h b/include/Asm/format.h index d02e7fd..da6dc06 100644 --- a/include/Asm/format.h +++ b/include/Asm/format.h @@ -18,15 +18,10 @@ #ifndef DEVEL_ASM_FORMAT_H # define DEVEL_ASM_FORMAT_H -# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) -# include -# elif defined(__linux__) -# include -# endif # include -/* As */ +/* AsmFormat */ /* types */ typedef struct _FormatPluginHelper { @@ -52,6 +47,9 @@ struct _FormatPlugin int (*section)(FormatPlugin * format, char const * section); char const * (*detect)(FormatPlugin * format); + /* FIXME: + * - put the callback in the helper structure + * - let a different architecture be specified in the callback */ int (*disas)(FormatPlugin * format, int (*callback)( FormatPlugin * format, char const * section, off_t offset, size_t size, off_t base)); @@ -59,36 +57,4 @@ struct _FormatPlugin void * priv; }; - -/* helpers */ -# if _BYTE_ORDER == _BIG_ENDIAN -# define _htob16(a) (a) -# define _htol16(a) (((a) & 0xff) << 8 | ((a) & 0xff00) >> 8) -# define _htob32(a) (a) -# define _htol32(a) (((a) & 0xff) << 24 | (((a) & 0xff00) << 8) \ - | (((a) & 0xff0000) >> 8) | ((a) & 0xff000000) >> 24) -# define _htob64(a) (a) -# define _htol64(a) (((a) & 0xff) << 56) | (((a) & 0xff00) << 40) \ - | (((a) & 0xff0000) << 24) | (((a) & 0xff000000) << 8) \ - | (((a) & 0xff00000000) >> 8) \ - | (((a) & 0xff0000000000) >> 24) \ - | (((a) & 0xff000000000000) >> 40) \ - | (((a) & 0xff00000000000000) >> 56) -# elif _BYTE_ORDER == _LITTLE_ENDIAN -# define _htob16(a) (((a) & 0xff) << 8 | ((a) & 0xff00) >> 8) -# define _htol16(a) (a) -# define _htob32(a) (((a) & 0xff) << 24 | (((a) & 0xff00) << 8) \ - | (((a) & 0xff0000) >> 8) | ((a) & 0xff000000) >> 24) -# define _htol32(a) (a) -# define _htob64(a) (((a) & 0xff) << 56) | (((a) & 0xff00) << 40) \ - | (((a) & 0xff0000) << 24) | (((a) & 0xff000000) << 8) \ - | (((a) & 0xff00000000) >> 8) \ - | (((a) & 0xff0000000000) >> 24) \ - | (((a) & 0xff000000000000) >> 40) \ - | (((a) & 0xff00000000000000) >> 56) -# define _htol64(a) (a) -# else -# warning "Could not determine endian on your system" -# endif - #endif /* !DEVEL_ASM_FORMAT_H */ diff --git a/src/arch.c b/src/arch.c index a1417a1..12be566 100644 --- a/src/arch.c +++ b/src/arch.c @@ -25,12 +25,18 @@ #include "arch.h" #include "../config.h" +/* macros */ +#ifndef abs +# define abs(a) ((a) >= 0 ? (a) : -(a)) +#endif + /* Arch */ /* private */ /* types */ struct _Arch { + ArchPluginHelper helper; Plugin * handle; ArchPlugin * plugin; size_t instructions_cnt; @@ -66,6 +72,7 @@ Arch * arch_new(char const * name) plugin_delete(handle); return NULL; } + memset(&a->helper, 0, sizeof(a->helper)); a->handle = handle; a->plugin = plugin; a->instructions_cnt = 0; @@ -99,8 +106,9 @@ ArchDescription * arch_get_description(Arch * arch) /* arch_get_format */ char const * arch_get_format(Arch * arch) { - if(arch->plugin->format != NULL) - return arch->plugin->format; + if(arch->plugin->description != NULL + && arch->plugin->description->format != NULL) + return arch->plugin->description->format; return "elf"; } @@ -144,7 +152,7 @@ ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size, ai = &arch->plugin->instructions[i]; if(AO_GET_SIZE(ai->opcode) != size) continue; - if(ai->value == opcode) + if(ai->opcode == opcode) return ai; } #if 0 @@ -162,17 +170,18 @@ ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size, } -/* arch_get_instruction_by_operands */ -static int _operands_operands(Arch * arch, ArchInstruction * ai, - AsOperand ** operands, size_t operands_cnt); -static int _operands_operands_dregister(Arch * arch, uint32_t operand, - AsOperand * aso); -static int _operands_operands_immediate(uint32_t operand, AsOperand * aso); -static int _operands_operands_register(Arch * arch, uint32_t operand, - AsOperand * aso); +/* arch_get_instruction_by_call */ +static int _call_operands(Arch * arch, ArchInstruction * ai, + ArchInstructionCall * call); +static int _call_operands_dregister(Arch * arch, + ArchOperandDefinition definition, ArchOperand * operand); +static int _call_operands_immediate(ArchOperandDefinition definition, + ArchOperand * operand); +static int _call_operands_register(Arch * arch, + ArchOperandDefinition definition, ArchOperand * operand); -ArchInstruction * arch_get_instruction_by_operands(Arch * arch, - char const * name, AsOperand ** operands, size_t operands_cnt) +ArchInstruction * arch_get_instruction_by_call(Arch * arch, + ArchInstructionCall * call) { size_t i; ArchInstruction * ai; @@ -185,50 +194,51 @@ ArchInstruction * arch_get_instruction_by_operands(Arch * arch, { ai = &arch->plugin->instructions[i]; /* FIXME use a (sorted) hash table */ - if(strcmp(ai->name, name) != 0) + if(strcmp(ai->name, call->name) != 0) continue; found = 1; - if(_operands_operands(arch, ai, operands, operands_cnt) == 0) + if(_call_operands(arch, ai, call) == 0) return ai; } error_set_code(1, "%s \"%s\"", found ? "Invalid arguments to" - : "Unknown instruction", name); + : "Unknown instruction", call->name); return NULL; } -static int _operands_operands(Arch * arch, ArchInstruction * ai, - AsOperand ** operands, size_t operands_cnt) +static int _call_operands(Arch * arch, ArchInstruction * ai, + ArchInstructionCall * call) { size_t i; - uint32_t operand; + ArchOperandDefinition definition; + ArchOperand * operand; - for(i = 0; i < operands_cnt; i++) + for(i = 0; i < call->operands_cnt; i++) { - if(i >= 3) - return -1; - operand = (i == 0) ? ai->op1 : ((i == 1) ? ai->op2 : ai->op3); + definition = (i == 0) ? ai->op1 : ((i == 1) ? ai->op2 + : ai->op3); + operand = &call->operands[i]; #ifdef DEBUG fprintf(stderr, "DEBUG: %s() operand %lu, type %u, type %u\n", - __func__, i, AO_GET_TYPE(operand), - AO_GET_TYPE(operands[i]->operand)); + __func__, i, AO_GET_TYPE(definition), + AO_GET_TYPE(operand->definition)); #endif - if(AO_GET_TYPE(operand) != AO_GET_TYPE(operands[i]->operand)) + if(AO_GET_TYPE(definition) != operand->type) return -1; - switch(AO_GET_TYPE(operand)) + switch(AO_GET_TYPE(definition)) { case AOT_IMMEDIATE: - if(_operands_operands_immediate(operand, - operands[i]) != 0) + if(_call_operands_immediate(definition, operand) + != 0) return -1; break; case AOT_DREGISTER: - if(_operands_operands_dregister(arch, operand, - operands[i]) != 0) + if(_call_operands_dregister(arch, definition, + operand) != 0) return -1; break; case AOT_REGISTER: - if(_operands_operands_register(arch, operand, - operands[i]) != 0) + if(_call_operands_register(arch, definition, + operand) != 0) return -1; break; } @@ -236,56 +246,48 @@ static int _operands_operands(Arch * arch, ArchInstruction * ai, return 0; } -static int _operands_operands_dregister(Arch * arch, uint32_t operand, - AsOperand * aso) +static int _call_operands_dregister(Arch * arch, + ArchOperandDefinition definition, ArchOperand * operand) { - unsigned long dereference; - unsigned long max; + uint64_t offset; #ifdef DEBUG - fprintf(stderr, "DEBUG: %s() %ld\n", __func__, aso->dereference); + fprintf(stderr, "DEBUG: %s() %ld\n", __func__, ao->dereference); #endif - if(_operands_operands_register(arch, operand, aso) != 0) + if(_call_operands_register(arch, definition, operand) != 0) return -1; - if(aso->dereference == 0) + /* check if there is an offset applied */ + if(operand->value.dregister.offset == 0) return 0; - dereference = (aso->dereference > 0) ? aso->dereference - : -aso->dereference; - /* check if the size fits */ - max = 1; - max <<= AO_GET_DSIZE(operand); - if(dereference > max - 1) + /* check if the offset fits */ + offset = abs(operand->value.dregister.offset); + offset >>= AO_GET_DSIZE(definition); + if(offset > 0) return -1; return 0; } -static int _operands_operands_immediate(uint32_t operand, AsOperand * aso) +static int _call_operands_immediate(ArchOperandDefinition definition, + ArchOperand * operand) { - unsigned long value; - long lvalue; - unsigned long max; + uint64_t value; + uint32_t size; /* check if the size fits */ - if(AO_GET_FLAGS(operand) & AOF_SIGNED) - { - lvalue = *(unsigned long*)aso->value; - value = (lvalue >= 0) ? lvalue : -lvalue; - } - else - value = *(unsigned long*)aso->value; - /* apply negative offset */ - if(AO_GET_FLAGS(operand) & AOF_SOFFSET) - value >>= AO_GET_OFFSET(operand); - max = 1; - max <<= AO_GET_SIZE(operand); - if(value > max - 1) + value = operand->value.immediate.value; + if((size = AO_GET_SIZE(definition)) > 0 + && AO_GET_FLAGS(definition) & AOF_SIGNED) + size--; + value >>= size; + if(value > 0) return -1; return 0; } -static int _operands_operands_register(Arch * arch, uint32_t operand, - AsOperand * aso) +static int _call_operands_register(Arch * arch, + ArchOperandDefinition definition, ArchOperand * operand) { + char const * name = operand->value._register.name; ArchDescription * desc; uint32_t size; ArchRegister * ar; @@ -295,14 +297,13 @@ static int _operands_operands_register(Arch * arch, uint32_t operand, && desc->instruction_size != 0) size = desc->instruction_size; else - size = AO_GET_SIZE(operand); + size = AO_GET_SIZE(definition); /* check if it exists */ - if((ar = arch_get_register_by_name_size(arch, aso->value, size)) - == NULL) + if((ar = arch_get_register_by_name_size(arch, name, size)) == NULL) return -1; /* for implicit instructions it must match */ - if(AO_GET_FLAGS(operand) & AOF_IMPLICIT - && AO_GET_VALUE(operand) != ar->id) + if(AO_GET_FLAGS(definition) & AOF_IMPLICIT + && AO_GET_VALUE(definition) != ar->id) return -1; return 0; } @@ -370,16 +371,34 @@ ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name, /* useful */ -/* arch_filter */ -int arch_filter(Arch * arch, ArchInstruction * instruction, ArchOperand operand, - unsigned char * buf, size_t size) +/* arch_exit */ +int arch_exit(Arch * arch) +{ + memset(&arch->helper, 0, sizeof(arch->helper)); + return 0; +} + + +/* arch_init */ +int arch_init(Arch * arch, char const * filename, FILE * fp) +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\", %p)\n", __func__, filename, + (void *)fp); +#endif + arch->helper.filename = filename; + arch->helper.fp = fp; + arch->plugin->helper = &arch->helper; + return 0; +} + + +/* arch_write */ +int arch_write(Arch * arch, ArchInstruction * instruction, + ArchInstructionCall * call) { #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, operand, buf, - size); + return arch->plugin->write(arch->plugin, instruction, call); } diff --git a/src/arch.h b/src/arch.h index 3d5ebbd..c1359bd 100644 --- a/src/arch.h +++ b/src/arch.h @@ -18,8 +18,8 @@ #ifndef ASM_ARCH_H # define ASM_ARCH_H -# include # include +# include # include "Asm.h" @@ -43,8 +43,8 @@ ArchInstruction * arch_get_instruction(Arch * arch, size_t index); ArchInstruction * arch_get_instruction_by_name(Arch * arch, char const * name); ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size, uint32_t opcode); -ArchInstruction * arch_get_instruction_by_operands(Arch * arch, - char const * name, AsOperand ** operands, size_t operands_cnt); +ArchInstruction * arch_get_instruction_by_call(Arch * arch, + ArchInstructionCall * call); ArchRegister * arch_get_register(Arch * arch, size_t index); ArchRegister * arch_get_register_by_id(Arch * arch, unsigned int id); @@ -53,7 +53,10 @@ ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name, uint32_t size); /* useful */ -int arch_filter(Arch * arch, ArchInstruction * ai, ArchOperand operand, - unsigned char * buf, size_t size); +int arch_init(Arch * arch, char const * filename, FILE * fp); +int arch_exit(Arch * arch); + +int arch_write(Arch * arch, ArchInstruction * instruction, + ArchInstructionCall * call); #endif /* !ASM_ARCH_H */ diff --git a/src/arch/i386.c b/src/arch/i386.c index 19cb348..6767818 100644 --- a/src/arch/i386.c +++ b/src/arch/i386.c @@ -16,10 +16,8 @@ #include -#ifdef DEBUG -# include -#endif -#include "Asm/arch.h" +#include +#include "Asm.h" /* i386 */ @@ -62,8 +60,8 @@ static ArchInstruction _i386_instructions[] = /* prototypes */ -static int _i386_filter(ArchPlugin * plugin, ArchInstruction * instruction, - ArchOperand operand, unsigned char * buf, size_t size); +static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction, + ArchInstructionCall * call); /* public */ @@ -71,32 +69,53 @@ static int _i386_filter(ArchPlugin * plugin, ArchInstruction * instruction, /* plug-in */ ArchPlugin arch_plugin = { + NULL, "i386", - "elf", NULL, _i386_registers, _i386_instructions, - _i386_filter + _i386_write, + NULL }; /* functions */ -static int _i386_filter(ArchPlugin * plugin, ArchInstruction * instruction, - ArchOperand operand, unsigned char * buf, size_t size) +static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction, + ArchInstructionCall * call) { + unsigned char * buf; + uint32_t size; + uint8_t u8; + uint16_t u16; + uint32_t u32; + #ifdef DEBUG - fprintf(stderr, "DEBUG: %s(\"%s\", 0x%08x) buf[0]=0x%02x\n", __func__, - instruction->name, operand, buf[0]); + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, instruction->name); #endif - /* the filter function is only set for mod r/m bytes at the moment */ - if(AO_GET_TYPE(operand) == AOT_REGISTER) - buf[0] |= 0xc0; - else if(AO_GET_TYPE(operand) == AOT_DREGISTER - && AO_GET_DSIZE(operand) == W) - buf[0] |= 0x80; - else if(AO_GET_TYPE(operand) == AOT_DREGISTER - && AO_GET_DSIZE(operand) == 8) - buf[0] |= 0x40; + /* opcode */ + size = (AO_GET_SIZE(instruction->flags) >> 3); + switch(size) + { + case 0: + break; + case sizeof(u8): + u8 = instruction->opcode; + buf = &u8; + break; + case sizeof(u16): + u16 = _htob16(instruction->opcode); + buf = &u16; + break; + case sizeof(u32): + u32 = _htob32(instruction->opcode); + buf = &u32; + break; + default: + return -1; + } + if(size > 0 && fwrite(buf, size, 1, plugin->helper->fp) != 1) + return -1; + /* FIXME implement the rest */ return 0; } diff --git a/src/arch/sparc.c b/src/arch/sparc.c index 3e59396..990164e 100644 --- a/src/arch/sparc.c +++ b/src/arch/sparc.c @@ -16,13 +16,13 @@ #include -#include "Asm/arch.h" +#include "Asm.h" /* sparc */ /* private */ /* variables */ -static ArchDescription _sparc_description = { ARCH_ENDIAN_BIG, 32, 32 }; +static ArchDescription _sparc_description = { "elf", ARCH_ENDIAN_BIG, 32, 32 }; #define REG(name, size, id) { "" # name, size, id }, static ArchRegister _sparc_registers[] = @@ -39,14 +39,39 @@ static ArchInstruction _sparc_instructions[] = }; +/* prototypes */ +/* plug-in */ +static int _sparc_write(ArchPlugin * arch, ArchInstruction * instruction, + ArchInstructionCall * call); + + /* protected */ /* variables */ ArchPlugin arch_plugin = { + NULL, "sparc", - "elf", &_sparc_description, _sparc_registers, _sparc_instructions, + _sparc_write, NULL }; + + +/* private */ +/* functions */ +/* plug-in */ +/* sparc_write */ +static int _sparc_write(ArchPlugin * arch, ArchInstruction * instruction, + ArchInstructionCall * call) +{ + uint32_t buf; + + buf = instruction->opcode; + /* FIXME implement the rest */ + buf = _htob32(buf); + if(fwrite(&buf, sizeof(buf), 1, arch->helper->fp) != 1) + return -1; + return 0; +} diff --git a/src/arch/sparc.ins b/src/arch/sparc.ins index 5acd77d..fd185d6 100644 --- a/src/arch/sparc.ins +++ b/src/arch/sparc.ins @@ -95,7 +95,7 @@ #define OPSHF (4 << AOD_SIZE) /* helpers */ #define OPSH(opcode) (opcode << 22) -#define OPSH_U21 AO_IMMEDIATE(AOF_SOFFSET, 10, 22) +#define OPSH_U21 AO_IMMEDIATE(0, 0, 32) /* instructions */ diff --git a/src/asm.c b/src/asm.c index 636788f..5d4a941 100644 --- a/src/asm.c +++ b/src/asm.c @@ -194,23 +194,24 @@ int as_function(As * as, char const * name) /* as_instruction */ int as_instruction(As * as, char const * name, unsigned int operands_cnt, ...) { - int ret; + ArchInstructionCall call; va_list ap; - AsOperand ** ao = NULL; size_t i; + ArchOperand * operand; - if(operands_cnt != 0) + memset(&call, 0, sizeof(call)); + call.name = name; + if((call.operands_cnt = operands_cnt) != 0) { - if((ao = malloc(sizeof(*ao) * operands_cnt)) == NULL) - return error_set_code(1, "%s", strerror(errno)); va_start(ap, operands_cnt); - for(i = 0; i < operands_cnt; i++) - ao[i] = va_arg(ap, AsOperand *); + for(i = 0; i < 3 && i < operands_cnt; i++) + { + operand = va_arg(ap, ArchOperand *); + memcpy(&call.operands[i], operand, sizeof(*operand)); + } va_end(ap); } - ret = code_instruction(as->code, name, ao, operands_cnt); - free(ao); - return ret; + return code_instruction(as->code, &call); } diff --git a/src/code.c b/src/code.c index 0cae3ca..db61d39 100644 --- a/src/code.c +++ b/src/code.c @@ -42,11 +42,6 @@ struct _Code }; -/* prototypes */ -static int _code_filter(Code * code, ArchInstruction * ai, ArchOperand operand, - unsigned char * buf, size_t size); - - /* functions */ /* code_new */ Code * code_new(char const * arch, char const * format) @@ -121,10 +116,11 @@ char const * code_get_format_name(Code * code) /* code_close */ int code_close(Code * code) { - int ret; + int ret = 0; - ret = format_exit(code->format); - if(fclose(code->fp) != 0) + ret |= arch_exit(code->arch); + ret |= format_exit(code->format); + if(fclose(code->fp) != 0 && ret == 0) ret |= -error_set_code(1, "%s: %s", code->filename, strerror(errno)); return ret; @@ -183,36 +179,37 @@ int code_function(Code * code, char const * function) /* code_instruction */ static int _instruction_fixed(Code * code, ArchInstruction * ai, - AsOperand ** operands, size_t operands_cnt); -static int _instruction_fixed_immediate(ArchOperand operand, AsOperand * aso, + ArchOperand ** operands, size_t operands_cnt); +static int _instruction_fixed_immediate(ArchOperand operand, ArchOperand * ao, uint32_t * pu); static int _instruction_fixed_register(Code * code, ArchOperand operand, - AsOperand * aso, uint32_t * pu); + ArchOperand * ao, uint32_t * pu); static int _instruction_variable(Code * code, ArchInstruction * ai, - AsOperand ** operands, size_t operands_cnt); + ArchOperand ** operands, size_t operands_cnt); static int _instruction_variable_dregister(Code * code, ArchInstruction * ai, - ArchOperand operand, AsOperand * aso); + ArchOperand operand, ArchOperand * ao); 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, ArchInstruction * ai, - ArchOperand operand, AsOperand * aso); + ArchOperand operand, ArchOperand * ao); static int _instruction_variable_register(Code * code, ArchInstruction * ai, - ArchOperand operand, AsOperand * aso); + ArchOperand operand, ArchOperand * ao); -int code_instruction(Code * code, char const * name, AsOperand ** operands, - size_t operands_cnt) +int code_instruction(Code * code, ArchInstructionCall * call) { ArchInstruction * ai; - if((ai = arch_get_instruction_by_operands(code->arch, name, operands, - operands_cnt)) == NULL) + if((ai = arch_get_instruction_by_call(code->arch, call)) == NULL) return -1; #ifdef DEBUG fprintf(stderr, "DEBUG: instruction %s, opcode 0x%x, 1 0x%x, 2 0x%x" - ", 3 0x%x\n", name, ai->value, ai->op1, ai->op2, + ", 3 0x%x\n", call->name, ai->opcode, ai->op1, ai->op2, ai->op3); #endif + return arch_write(code->arch, ai, call); +} +#if 0 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); @@ -490,6 +487,7 @@ static int _instruction_variable_register(Code * code, ArchInstruction * ai, return _instruction_variable_immediate(code, ai, operand, &value, 0); } #endif +#endif #if 0 switch(AO_GET_SIZE(ai->opcode)) { @@ -655,7 +653,8 @@ int code_open(Code * code, char const * filename) return -1; if((code->fp = fopen(filename, "w+")) == NULL) return -error_set_code(1, "%s: %s", filename, strerror(errno)); - if(format_init(code->format, code->filename, code->fp) != 0) + if(format_init(code->format, code->filename, code->fp) != 0 + || arch_init(code->arch, code->filename, code->fp) != 0) { fclose(code->fp); code->fp = NULL; @@ -676,13 +675,3 @@ 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, ArchOperand operand, - unsigned char * buf, size_t size) -{ - return arch_filter(code->arch, ai, operand, buf, size); -} diff --git a/src/code.h b/src/code.h index 625bbad..e3cd689 100644 --- a/src/code.h +++ b/src/code.h @@ -46,8 +46,7 @@ int code_close(Code * code); ArchInstruction * code_decode(Code * code, char const * buffer, size_t * size); int code_function(Code * code, char const * function); -int code_instruction(Code * code, char const * name, AsOperand ** operands, - size_t operands_cnt); +int code_instruction(Code * code, ArchInstructionCall * call); int code_section(Code * code, char const * section); #endif /* !ASM_CODE_H */ diff --git a/src/format.c b/src/format.c index 33f5cdd..97e4cac 100644 --- a/src/format.c +++ b/src/format.c @@ -30,11 +30,10 @@ /* types */ struct _Format { - char * name; char * arch; FormatPluginHelper helper; - FormatPlugin * plugin; Plugin * handle; + FormatPlugin * plugin; }; @@ -60,8 +59,8 @@ Format * format_new(char const * format, char const * arch) plugin_delete(handle); return NULL; } - f->name = string_new(format); f->arch = string_new(arch); + memset(&f->helper, 0, sizeof(f->helper)); f->plugin = plugin; f->handle = handle; if(f->arch == NULL) @@ -78,7 +77,6 @@ void format_delete(Format * format) { plugin_delete(format->handle); string_delete(format->arch); - string_delete(format->name); object_delete(format); } @@ -87,7 +85,7 @@ void format_delete(Format * format) /* format_get_name */ char const * format_get_name(Format * format) { - return format->name; + return format->plugin->name; } diff --git a/src/format/dex.c b/src/format/dex.c index c7080db..814445c 100644 --- a/src/format/dex.c +++ b/src/format/dex.c @@ -20,7 +20,7 @@ #include #include #include -#include "Asm/format.h" +#include "Asm.h" /* DEX */ diff --git a/src/format/elf.c b/src/format/elf.c index c9fb0a7..1943920 100644 --- a/src/format/elf.c +++ b/src/format/elf.c @@ -21,7 +21,7 @@ #include #include #include -#include "Asm/format.h" +#include "Asm.h" /* portability */ #define Elf64_Quarter unsigned char diff --git a/src/format/flat.c b/src/format/flat.c index 035e6f9..57402bf 100644 --- a/src/format/flat.c +++ b/src/format/flat.c @@ -19,7 +19,7 @@ #include #include #include -#include "Asm/format.h" +#include "Asm.h" /* Flat */ diff --git a/src/format/java.c b/src/format/java.c index 8b88ac0..cc11635 100644 --- a/src/format/java.c +++ b/src/format/java.c @@ -22,7 +22,7 @@ #include #include #include -#include "Asm/format.h" +#include "Asm.h" /* Java */ diff --git a/src/format/pe.c b/src/format/pe.c index 40745ce..e2b6286 100644 --- a/src/format/pe.c +++ b/src/format/pe.c @@ -21,7 +21,7 @@ #include #include #include -#include "Asm/format.h" +#include "Asm.h" /* PE */ diff --git a/src/parser.c b/src/parser.c index 7bbb377..6b163fa 100644 --- a/src/parser.c +++ b/src/parser.c @@ -34,9 +34,16 @@ typedef struct _State unsigned int error_cnt; unsigned int warning_cnt; Code * code; - char * operator; - AsOperand ** operands; + ArchInstructionCall call; +#if 0 + char const * name; + struct + { + ArchOperandDefinition definition; + ArchOperand operand; + } operands[3]; size_t operands_cnt; +#endif } State; @@ -209,7 +216,6 @@ int parser(Code * code, char const * infile) " warning(s)"); if(state.token != NULL) token_delete(state.token); - free(state.operands); return state.error_cnt; } @@ -386,7 +392,6 @@ static int _instruction(State * state) /* operator [ space [ operand_list ] ] newline */ { int ret; - size_t i; #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); @@ -398,22 +403,14 @@ static int _instruction(State * state) if(_parser_in_set(state, TS_OPERAND_LIST)) ret |= _operand_list(state); } - if(state->operator != NULL) + if(state->call.name != NULL) { - if(code_instruction(state->code, state->operator, - state->operands, state->operands_cnt)) + if(code_instruction(state->code, &state->call) != 0) ret |= _parser_error(state, "%s", error_get()); - free(state->operator); - state->operator = NULL; + free(state->call.name); } - for(i = 0; i < state->operands_cnt; i++) - { - free(state->operands[i]->value2); - free(state->operands[i]->value); - free(state->operands[i]); - } - /* optimized free(state->operands); out */ - state->operands_cnt = 0; + /* FIXME memory leak (register names...) */ + memset(&state->call, 0, sizeof(state->call)); return ret | _newline(state); } @@ -423,7 +420,6 @@ static int _operator(State * state) /* WORD */ { char const * string; - char * operator = NULL; #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); @@ -433,12 +429,11 @@ static int _operator(State * state) _parser_scan(state); return 1; } - if((operator = strdup(string)) == NULL) + if((state->call.name = strdup(string)) == NULL) return error_set_code(1, "%s", strerror(errno)); /* optimized free(state->operator); out */ - state->operator = operator; #ifdef DEBUG - fprintf(stderr, "%s \"%s\"\n", "DEBUG: operator", operator); + fprintf(stderr, "%s \"%s\"\n", "DEBUG: operator", string); #endif return _parser_scan(state); } @@ -478,9 +473,7 @@ static int _operand(State * state) int ret = 0; TokenCode code; char const * string; - AsOperand ** p; - unsigned long * l; - unsigned long * u; + ArchOperand * p; if(state->token == NULL) return 1; @@ -499,74 +492,40 @@ static int _operand(State * state) fprintf(stderr, "%s%s\"\n", "DEBUG: new operand: \"", token_get_string(state->token)); #endif - if((p = realloc(state->operands, (state->operands_cnt + 1) - * sizeof(*p))) == NULL) - ret |= _parser_error(state, "%s", strerror(errno)); - else if((p[state->operands_cnt] = malloc(sizeof(**p))) == NULL) + p = &state->call.operands[state->call.operands_cnt]; + switch(token_get_code(state->token)) { - state->operands = p; - ret |= _parser_error(state, "%s", strerror(errno)); - } - else - { - state->operands = p; - p = &state->operands[state->operands_cnt]; - (*p)->operand = 0; - (*p)->dereference = 0; - (*p)->value = NULL; - (*p)->value2 = NULL; - switch(token_get_code(state->token)) - { - case AS_CODE_OPERATOR_MINUS: - ret |= _parser_scan(state); - /* FIXME check if a number */ - string = token_get_string(state->token); - if(string == NULL) - break; - (*p)->operand = AO_IMMEDIATE(AOF_SIGNED, - 0, 0); - if((l = malloc(sizeof(*l))) == NULL) - { - ret |= _parser_error(state, - "%s", strerror( - errno)); - break; - } - /* FIXME also true for numbers? */ - *l = -strtoul(string + 1, NULL, 0); - (*p)->value = l; - break; - case AS_CODE_IMMEDIATE: - case AS_CODE_NUMBER: - (*p)->operand = AO_IMMEDIATE(0, 0, 0); - if((u = malloc(sizeof(*u))) == NULL) - { - ret |= _parser_error(state, - "%s", strerror( - errno)); - break; - } - /* FIXME also true for numbers? */ - *u = strtoul(string + 1, NULL, 0); - (*p)->value = u; - break; - case AS_CODE_REGISTER: - if(code == AS_CODE_OPERATOR_LBRACKET) - (*p)->operand = AO_DREGISTER(0, - 0, 0, 0); - else - (*p)->operand = AO_REGISTER(0, - 0, 0); - /* FIXME check errors */ - (*p)->value = strdup(string); - break; - default: - ret |= _parser_error(state, "%s", - "Expected value"); - break; - } - state->operands_cnt++; + case AS_CODE_OPERATOR_MINUS: + ret |= _parser_scan(state); + /* FIXME check if a number */ + string = token_get_string(state->token); + if(string == NULL) + break; + p->type = AOT_IMMEDIATE; + /* FIXME also true for numbers? */ + p->value.immediate.value = strtoul(string + 1, + NULL, 0); + p->value.immediate.negative = 1; + break; + case AS_CODE_IMMEDIATE: + case AS_CODE_NUMBER: + p->type = AOT_IMMEDIATE; + /* FIXME also true for numbers? */ + p->value.immediate.value = strtoul(string + 1, + NULL, 0); + break; + case AS_CODE_REGISTER: + p->type = (code == AS_CODE_OPERATOR_LBRACKET) + ? AOT_DREGISTER : AOT_REGISTER; + /* FIXME check errors */ + p->value._register.name = strdup(string); + break; + default: + ret |= _parser_error(state, "%s", + "Expected value"); + break; } + state->call.operands_cnt++; } ret |= _parser_scan(state); if(code == AS_CODE_OPERATOR_LBRACKET) @@ -574,27 +533,29 @@ static int _operand(State * state) if(_parser_in_set(state, TS_SPACE)) ret |= _space(state); + /* FIXME implement AS_CODE_OPERATOR_MINUS too */ if(_parser_is_code(state, AS_CODE_OPERATOR_PLUS)) { ret |= _parser_scan(state); if(_parser_in_set(state, TS_SPACE)) ret |= _space(state); - /* FIXME register or immediate value */ - p = &state->operands[state->operands_cnt - 1]; /* XXX */ + /* XXX this is quite ugly */ + p = &state->call.operands[state->call.operands_cnt - 1]; string = token_get_string(state->token); switch(token_get_code(state->token)) { case AS_CODE_IMMEDIATE: - (*p)->operand = AO_DREGISTER(0, 0, 0, - 0); - (*p)->dereference = strtoul(string + 1, - NULL, 0); + p->value.dregister.offset = strtoul( + string + 1, NULL, 0); break; case AS_CODE_REGISTER: /* FIXME check everything... */ - (*p)->operand = AO_DREGISTER2(0, 0, 0, - 0); - (*p)->value2 = strdup(string); + p->type = AOT_DREGISTER2; + p->value.dregister2.name2 = strdup( + string); + break; + default: + /* FIXME report an error */ break; } ret |= _parser_scan(state);