Letting each plug-in output instructions as it pleases

This commit is contained in:
Pierre Pronchery 2011-04-15 18:48:08 +00:00
parent 77f32dfab2
commit 95834007bc
19 changed files with 395 additions and 326 deletions

View File

@ -18,8 +18,47 @@
#ifndef DEVEL_ASM_H #ifndef DEVEL_ASM_H
# define DEVEL_ASM_H # define DEVEL_ASM_H
# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
# include <sys/endian.h>
# elif defined(__linux__)
# include <endian.h>
# endif
# include "Asm/arch.h" # include "Asm/arch.h"
# include "Asm/asm.h" # include "Asm/asm.h"
# include "Asm/format.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 */ #endif /* !DEVEL_ASM_H */

View File

@ -19,9 +19,10 @@
# define DEVEL_ASM_ARCH_H # define DEVEL_ASM_ARCH_H
# include <stdint.h> # include <stdint.h>
# include <stdio.h>
/* AsArch */ /* AsmArch */
/* types */ /* types */
typedef enum _ArchEndian typedef enum _ArchEndian
{ {
@ -32,19 +33,22 @@ typedef enum _ArchEndian
typedef struct _ArchDescription typedef struct _ArchDescription
{ {
char const * format; /* default format */
ArchEndian endian; ArchEndian endian;
uint32_t alignment; uint32_t alignment;
uint32_t instruction_size; /* 0 if not constant */ uint32_t instruction_size; /* 0 if not constant */
} ArchDescription; } ArchDescription;
/* operands */ /* operands */
typedef uint32_t ArchOperand; typedef enum _ArchOperandType
# define AOT_NONE 0x0 {
# define AOT_CONSTANT 0x1 /* flags | 0 | size | value */ AOT_NONE = 0x0,
# define AOT_IMMEDIATE 0x2 /* flags | offset | 0 | size */ AOT_CONSTANT = 0x1, /* flags | 0 | size | value */
# define AOT_REGISTER 0x3 /* flags | 0 | size | id */ AOT_IMMEDIATE = 0x2, /* flags | offset | 0 | size */
# define AOT_DREGISTER 0x4 /* flags | dsize | rsize | id */ AOT_REGISTER = 0x3, /* flags | 0 | size | id */
# define AOT_DREGISTER2 0x5 /* flags | did | rsize | id */ AOT_DREGISTER = 0x4, /* flags | dsize | rsize | id */
AOT_DREGISTER2 = 0x5 /* flags | did | rsize | id */
} ArchOperandType;
/* displacement */ /* displacement */
# define AOD_FLAGS 24 # define AOD_FLAGS 24
@ -62,11 +66,10 @@ typedef uint32_t ArchOperand;
/* flags */ /* flags */
# define AOF_FILTER 0x1 # define AOF_FILTER 0x1
# define AOF_SOFFSET 0x2
/* for immediate */ /* for immediate */
# define AOF_SIGNED 0x4 # define AOF_SIGNED 0x2
/* for registers */ /* for registers */
# define AOF_IMPLICIT 0x4 # define AOF_IMPLICIT 0x2
/* macros */ /* macros */
# define AO_GET_FLAGS(operand) ((operand & AOM_FLAGS) >> AOD_FLAGS) # define AO_GET_FLAGS(operand) ((operand & AOM_FLAGS) >> AOD_FLAGS)
@ -100,16 +103,60 @@ typedef uint32_t ArchOperand;
| ((dsize) << AOD_SIZE) \ | ((dsize) << AOD_SIZE) \
| ((id) << AOD_VALUE)) | ((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 typedef struct _ArchInstruction
{ {
char * name; char * name;
uint32_t value; uint32_t opcode;
ArchOperand opcode; ArchOperandDefinition flags;
ArchOperand op1; ArchOperandDefinition op1;
ArchOperand op2; ArchOperandDefinition op2;
ArchOperand op3; ArchOperandDefinition op3;
} ArchInstruction; } ArchInstruction;
typedef struct _ArchInstructionCall
{
char * name;
ArchOperand operands[3];
size_t operands_cnt;
} ArchInstructionCall;
typedef struct _ArchRegister typedef struct _ArchRegister
{ {
char * name; char * name;
@ -117,17 +164,29 @@ typedef struct _ArchRegister
uint32_t id; uint32_t id;
} ArchRegister; } ArchRegister;
typedef struct _ArchPluginHelper
{
char const * filename;
FILE * fp;
void * priv;
} ArchPluginHelper;
typedef struct _ArchPlugin ArchPlugin; typedef struct _ArchPlugin ArchPlugin;
struct _ArchPlugin struct _ArchPlugin
{ {
ArchPluginHelper * helper;
char const * name; char const * name;
char const * format; /* default format */
ArchDescription * description; ArchDescription * description;
ArchRegister * registers; ArchRegister * registers;
ArchInstruction * instructions; 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 */ #endif /* !DEVEL_ASM_ARCH_H */

View File

@ -26,15 +26,6 @@
/* types */ /* types */
typedef struct _As As; 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; typedef enum _AsPluginType { ASPT_ARCH = 0, ASPT_FORMAT } AsPluginType;

View File

@ -18,15 +18,10 @@
#ifndef DEVEL_ASM_FORMAT_H #ifndef DEVEL_ASM_FORMAT_H
# define DEVEL_ASM_FORMAT_H # define DEVEL_ASM_FORMAT_H
# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
# include <sys/endian.h>
# elif defined(__linux__)
# include <endian.h>
# endif
# include <stdio.h> # include <stdio.h>
/* As */ /* AsmFormat */
/* types */ /* types */
typedef struct _FormatPluginHelper typedef struct _FormatPluginHelper
{ {
@ -52,6 +47,9 @@ struct _FormatPlugin
int (*section)(FormatPlugin * format, char const * section); int (*section)(FormatPlugin * format, char const * section);
char const * (*detect)(FormatPlugin * format); 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)( int (*disas)(FormatPlugin * format, int (*callback)(
FormatPlugin * format, char const * section, FormatPlugin * format, char const * section,
off_t offset, size_t size, off_t base)); off_t offset, size_t size, off_t base));
@ -59,36 +57,4 @@ struct _FormatPlugin
void * priv; 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 */ #endif /* !DEVEL_ASM_FORMAT_H */

View File

@ -25,12 +25,18 @@
#include "arch.h" #include "arch.h"
#include "../config.h" #include "../config.h"
/* macros */
#ifndef abs
# define abs(a) ((a) >= 0 ? (a) : -(a))
#endif
/* Arch */ /* Arch */
/* private */ /* private */
/* types */ /* types */
struct _Arch struct _Arch
{ {
ArchPluginHelper helper;
Plugin * handle; Plugin * handle;
ArchPlugin * plugin; ArchPlugin * plugin;
size_t instructions_cnt; size_t instructions_cnt;
@ -66,6 +72,7 @@ Arch * arch_new(char const * name)
plugin_delete(handle); plugin_delete(handle);
return NULL; return NULL;
} }
memset(&a->helper, 0, sizeof(a->helper));
a->handle = handle; a->handle = handle;
a->plugin = plugin; a->plugin = plugin;
a->instructions_cnt = 0; a->instructions_cnt = 0;
@ -99,8 +106,9 @@ ArchDescription * arch_get_description(Arch * arch)
/* arch_get_format */ /* arch_get_format */
char const * arch_get_format(Arch * arch) char const * arch_get_format(Arch * arch)
{ {
if(arch->plugin->format != NULL) if(arch->plugin->description != NULL
return arch->plugin->format; && arch->plugin->description->format != NULL)
return arch->plugin->description->format;
return "elf"; return "elf";
} }
@ -144,7 +152,7 @@ ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size,
ai = &arch->plugin->instructions[i]; ai = &arch->plugin->instructions[i];
if(AO_GET_SIZE(ai->opcode) != size) if(AO_GET_SIZE(ai->opcode) != size)
continue; continue;
if(ai->value == opcode) if(ai->opcode == opcode)
return ai; return ai;
} }
#if 0 #if 0
@ -162,17 +170,18 @@ ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size,
} }
/* arch_get_instruction_by_operands */ /* arch_get_instruction_by_call */
static int _operands_operands(Arch * arch, ArchInstruction * ai, static int _call_operands(Arch * arch, ArchInstruction * ai,
AsOperand ** operands, size_t operands_cnt); ArchInstructionCall * call);
static int _operands_operands_dregister(Arch * arch, uint32_t operand, static int _call_operands_dregister(Arch * arch,
AsOperand * aso); ArchOperandDefinition definition, ArchOperand * operand);
static int _operands_operands_immediate(uint32_t operand, AsOperand * aso); static int _call_operands_immediate(ArchOperandDefinition definition,
static int _operands_operands_register(Arch * arch, uint32_t operand, ArchOperand * operand);
AsOperand * aso); static int _call_operands_register(Arch * arch,
ArchOperandDefinition definition, ArchOperand * operand);
ArchInstruction * arch_get_instruction_by_operands(Arch * arch, ArchInstruction * arch_get_instruction_by_call(Arch * arch,
char const * name, AsOperand ** operands, size_t operands_cnt) ArchInstructionCall * call)
{ {
size_t i; size_t i;
ArchInstruction * ai; ArchInstruction * ai;
@ -185,50 +194,51 @@ ArchInstruction * arch_get_instruction_by_operands(Arch * arch,
{ {
ai = &arch->plugin->instructions[i]; ai = &arch->plugin->instructions[i];
/* FIXME use a (sorted) hash table */ /* FIXME use a (sorted) hash table */
if(strcmp(ai->name, name) != 0) if(strcmp(ai->name, call->name) != 0)
continue; continue;
found = 1; found = 1;
if(_operands_operands(arch, ai, operands, operands_cnt) == 0) if(_call_operands(arch, ai, call) == 0)
return ai; return ai;
} }
error_set_code(1, "%s \"%s\"", found ? "Invalid arguments to" error_set_code(1, "%s \"%s\"", found ? "Invalid arguments to"
: "Unknown instruction", name); : "Unknown instruction", call->name);
return NULL; return NULL;
} }
static int _operands_operands(Arch * arch, ArchInstruction * ai, static int _call_operands(Arch * arch, ArchInstruction * ai,
AsOperand ** operands, size_t operands_cnt) ArchInstructionCall * call)
{ {
size_t i; 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) definition = (i == 0) ? ai->op1 : ((i == 1) ? ai->op2
return -1; : ai->op3);
operand = (i == 0) ? ai->op1 : ((i == 1) ? ai->op2 : ai->op3); operand = &call->operands[i];
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "DEBUG: %s() operand %lu, type %u, type %u\n", fprintf(stderr, "DEBUG: %s() operand %lu, type %u, type %u\n",
__func__, i, AO_GET_TYPE(operand), __func__, i, AO_GET_TYPE(definition),
AO_GET_TYPE(operands[i]->operand)); AO_GET_TYPE(operand->definition));
#endif #endif
if(AO_GET_TYPE(operand) != AO_GET_TYPE(operands[i]->operand)) if(AO_GET_TYPE(definition) != operand->type)
return -1; return -1;
switch(AO_GET_TYPE(operand)) switch(AO_GET_TYPE(definition))
{ {
case AOT_IMMEDIATE: case AOT_IMMEDIATE:
if(_operands_operands_immediate(operand, if(_call_operands_immediate(definition, operand)
operands[i]) != 0) != 0)
return -1; return -1;
break; break;
case AOT_DREGISTER: case AOT_DREGISTER:
if(_operands_operands_dregister(arch, operand, if(_call_operands_dregister(arch, definition,
operands[i]) != 0) operand) != 0)
return -1; return -1;
break; break;
case AOT_REGISTER: case AOT_REGISTER:
if(_operands_operands_register(arch, operand, if(_call_operands_register(arch, definition,
operands[i]) != 0) operand) != 0)
return -1; return -1;
break; break;
} }
@ -236,56 +246,48 @@ static int _operands_operands(Arch * arch, ArchInstruction * ai,
return 0; return 0;
} }
static int _operands_operands_dregister(Arch * arch, uint32_t operand, static int _call_operands_dregister(Arch * arch,
AsOperand * aso) ArchOperandDefinition definition, ArchOperand * operand)
{ {
unsigned long dereference; uint64_t offset;
unsigned long max;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "DEBUG: %s() %ld\n", __func__, aso->dereference); fprintf(stderr, "DEBUG: %s() %ld\n", __func__, ao->dereference);
#endif #endif
if(_operands_operands_register(arch, operand, aso) != 0) if(_call_operands_register(arch, definition, operand) != 0)
return -1; return -1;
if(aso->dereference == 0) /* check if there is an offset applied */
if(operand->value.dregister.offset == 0)
return 0; return 0;
dereference = (aso->dereference > 0) ? aso->dereference /* check if the offset fits */
: -aso->dereference; offset = abs(operand->value.dregister.offset);
/* check if the size fits */ offset >>= AO_GET_DSIZE(definition);
max = 1; if(offset > 0)
max <<= AO_GET_DSIZE(operand);
if(dereference > max - 1)
return -1; return -1;
return 0; return 0;
} }
static int _operands_operands_immediate(uint32_t operand, AsOperand * aso) static int _call_operands_immediate(ArchOperandDefinition definition,
ArchOperand * operand)
{ {
unsigned long value; uint64_t value;
long lvalue; uint32_t size;
unsigned long max;
/* check if the size fits */ /* check if the size fits */
if(AO_GET_FLAGS(operand) & AOF_SIGNED) value = operand->value.immediate.value;
{ if((size = AO_GET_SIZE(definition)) > 0
lvalue = *(unsigned long*)aso->value; && AO_GET_FLAGS(definition) & AOF_SIGNED)
value = (lvalue >= 0) ? lvalue : -lvalue; size--;
} value >>= size;
else if(value > 0)
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)
return -1; return -1;
return 0; return 0;
} }
static int _operands_operands_register(Arch * arch, uint32_t operand, static int _call_operands_register(Arch * arch,
AsOperand * aso) ArchOperandDefinition definition, ArchOperand * operand)
{ {
char const * name = operand->value._register.name;
ArchDescription * desc; ArchDescription * desc;
uint32_t size; uint32_t size;
ArchRegister * ar; ArchRegister * ar;
@ -295,14 +297,13 @@ static int _operands_operands_register(Arch * arch, uint32_t operand,
&& desc->instruction_size != 0) && desc->instruction_size != 0)
size = desc->instruction_size; size = desc->instruction_size;
else else
size = AO_GET_SIZE(operand); size = AO_GET_SIZE(definition);
/* check if it exists */ /* check if it exists */
if((ar = arch_get_register_by_name_size(arch, aso->value, size)) if((ar = arch_get_register_by_name_size(arch, name, size)) == NULL)
== NULL)
return -1; return -1;
/* for implicit instructions it must match */ /* for implicit instructions it must match */
if(AO_GET_FLAGS(operand) & AOF_IMPLICIT if(AO_GET_FLAGS(definition) & AOF_IMPLICIT
&& AO_GET_VALUE(operand) != ar->id) && AO_GET_VALUE(definition) != ar->id)
return -1; return -1;
return 0; return 0;
} }
@ -370,16 +371,34 @@ ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name,
/* useful */ /* useful */
/* arch_filter */ /* arch_exit */
int arch_filter(Arch * arch, ArchInstruction * instruction, ArchOperand operand, int arch_exit(Arch * arch)
unsigned char * buf, size_t size) {
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 #ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, instruction->name); fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, instruction->name);
#endif #endif
if(arch->plugin->filter == NULL) return arch->plugin->write(arch->plugin, instruction, call);
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);
} }

View File

@ -18,8 +18,8 @@
#ifndef ASM_ARCH_H #ifndef ASM_ARCH_H
# define ASM_ARCH_H # define ASM_ARCH_H
# include <sys/types.h>
# include <stdint.h> # include <stdint.h>
# include <stdio.h>
# include "Asm.h" # 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_name(Arch * arch, char const * name);
ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size, ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size,
uint32_t opcode); uint32_t opcode);
ArchInstruction * arch_get_instruction_by_operands(Arch * arch, ArchInstruction * arch_get_instruction_by_call(Arch * arch,
char const * name, AsOperand ** operands, size_t operands_cnt); ArchInstructionCall * call);
ArchRegister * arch_get_register(Arch * arch, size_t index); 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_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); uint32_t size);
/* useful */ /* useful */
int arch_filter(Arch * arch, ArchInstruction * ai, ArchOperand operand, int arch_init(Arch * arch, char const * filename, FILE * fp);
unsigned char * buf, size_t size); int arch_exit(Arch * arch);
int arch_write(Arch * arch, ArchInstruction * instruction,
ArchInstructionCall * call);
#endif /* !ASM_ARCH_H */ #endif /* !ASM_ARCH_H */

View File

@ -16,10 +16,8 @@
#include <stddef.h> #include <stddef.h>
#ifdef DEBUG #include <string.h>
# include <stdio.h> #include "Asm.h"
#endif
#include "Asm/arch.h"
/* i386 */ /* i386 */
@ -62,8 +60,8 @@ static ArchInstruction _i386_instructions[] =
/* prototypes */ /* prototypes */
static int _i386_filter(ArchPlugin * plugin, ArchInstruction * instruction, static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction,
ArchOperand operand, unsigned char * buf, size_t size); ArchInstructionCall * call);
/* public */ /* public */
@ -71,32 +69,53 @@ static int _i386_filter(ArchPlugin * plugin, ArchInstruction * instruction,
/* plug-in */ /* plug-in */
ArchPlugin arch_plugin = ArchPlugin arch_plugin =
{ {
NULL,
"i386", "i386",
"elf",
NULL, NULL,
_i386_registers, _i386_registers,
_i386_instructions, _i386_instructions,
_i386_filter _i386_write,
NULL
}; };
/* functions */ /* functions */
static int _i386_filter(ArchPlugin * plugin, ArchInstruction * instruction, static int _i386_write(ArchPlugin * plugin, ArchInstruction * instruction,
ArchOperand operand, unsigned char * buf, size_t size) ArchInstructionCall * call)
{ {
unsigned char * buf;
uint32_t size;
uint8_t u8;
uint16_t u16;
uint32_t u32;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\", 0x%08x) buf[0]=0x%02x\n", __func__, fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, instruction->name);
instruction->name, operand, buf[0]);
#endif #endif
/* the filter function is only set for mod r/m bytes at the moment */ /* opcode */
if(AO_GET_TYPE(operand) == AOT_REGISTER) size = (AO_GET_SIZE(instruction->flags) >> 3);
buf[0] |= 0xc0; switch(size)
else if(AO_GET_TYPE(operand) == AOT_DREGISTER {
&& AO_GET_DSIZE(operand) == W) case 0:
buf[0] |= 0x80; break;
else if(AO_GET_TYPE(operand) == AOT_DREGISTER case sizeof(u8):
&& AO_GET_DSIZE(operand) == 8) u8 = instruction->opcode;
buf[0] |= 0x40; 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; return 0;
} }

View File

@ -16,13 +16,13 @@
#include <stddef.h> #include <stddef.h>
#include "Asm/arch.h" #include "Asm.h"
/* sparc */ /* sparc */
/* private */ /* private */
/* variables */ /* 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 }, #define REG(name, size, id) { "" # name, size, id },
static ArchRegister _sparc_registers[] = 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 */ /* protected */
/* variables */ /* variables */
ArchPlugin arch_plugin = ArchPlugin arch_plugin =
{ {
NULL,
"sparc", "sparc",
"elf",
&_sparc_description, &_sparc_description,
_sparc_registers, _sparc_registers,
_sparc_instructions, _sparc_instructions,
_sparc_write,
NULL 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;
}

View File

@ -95,7 +95,7 @@
#define OPSHF (4 << AOD_SIZE) #define OPSHF (4 << AOD_SIZE)
/* helpers */ /* helpers */
#define OPSH(opcode) (opcode << 22) #define OPSH(opcode) (opcode << 22)
#define OPSH_U21 AO_IMMEDIATE(AOF_SOFFSET, 10, 22) #define OPSH_U21 AO_IMMEDIATE(0, 0, 32)
/* instructions */ /* instructions */

View File

@ -194,23 +194,24 @@ int as_function(As * as, char const * name)
/* as_instruction */ /* as_instruction */
int as_instruction(As * as, char const * name, unsigned int operands_cnt, ...) int as_instruction(As * as, char const * name, unsigned int operands_cnt, ...)
{ {
int ret; ArchInstructionCall call;
va_list ap; va_list ap;
AsOperand ** ao = NULL;
size_t i; 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); va_start(ap, operands_cnt);
for(i = 0; i < operands_cnt; i++) for(i = 0; i < 3 && i < operands_cnt; i++)
ao[i] = va_arg(ap, AsOperand *); {
operand = va_arg(ap, ArchOperand *);
memcpy(&call.operands[i], operand, sizeof(*operand));
}
va_end(ap); va_end(ap);
} }
ret = code_instruction(as->code, name, ao, operands_cnt); return code_instruction(as->code, &call);
free(ao);
return ret;
} }

View File

@ -42,11 +42,6 @@ struct _Code
}; };
/* prototypes */
static int _code_filter(Code * code, ArchInstruction * ai, ArchOperand operand,
unsigned char * buf, size_t size);
/* functions */ /* functions */
/* code_new */ /* code_new */
Code * code_new(char const * arch, char const * format) Code * code_new(char const * arch, char const * format)
@ -121,10 +116,11 @@ char const * code_get_format_name(Code * code)
/* code_close */ /* code_close */
int code_close(Code * code) int code_close(Code * code)
{ {
int ret; int ret = 0;
ret = format_exit(code->format); ret |= arch_exit(code->arch);
if(fclose(code->fp) != 0) ret |= format_exit(code->format);
if(fclose(code->fp) != 0 && ret == 0)
ret |= -error_set_code(1, "%s: %s", code->filename, ret |= -error_set_code(1, "%s: %s", code->filename,
strerror(errno)); strerror(errno));
return ret; return ret;
@ -183,36 +179,37 @@ int code_function(Code * code, char const * function)
/* code_instruction */ /* code_instruction */
static int _instruction_fixed(Code * code, ArchInstruction * ai, static int _instruction_fixed(Code * code, ArchInstruction * ai,
AsOperand ** operands, size_t operands_cnt); ArchOperand ** operands, size_t operands_cnt);
static int _instruction_fixed_immediate(ArchOperand operand, AsOperand * aso, static int _instruction_fixed_immediate(ArchOperand operand, ArchOperand * ao,
uint32_t * pu); uint32_t * pu);
static int _instruction_fixed_register(Code * code, ArchOperand operand, 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, 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, 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, static int _instruction_variable_immediate(Code * code, ArchInstruction * ai,
ArchOperand operand, void * value, int swap); ArchOperand operand, void * value, int swap);
static int _instruction_variable_opcode(Code * code, ArchInstruction * ai); static int _instruction_variable_opcode(Code * code, ArchInstruction * ai);
static int _instruction_variable_operand(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, 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, int code_instruction(Code * code, ArchInstructionCall * call)
size_t operands_cnt)
{ {
ArchInstruction * ai; ArchInstruction * ai;
if((ai = arch_get_instruction_by_operands(code->arch, name, operands, if((ai = arch_get_instruction_by_call(code->arch, call)) == NULL)
operands_cnt)) == NULL)
return -1; return -1;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "DEBUG: instruction %s, opcode 0x%x, 1 0x%x, 2 0x%x" 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); ai->op3);
#endif #endif
return arch_write(code->arch, ai, call);
}
#if 0
if(code->description != NULL && code->description->instruction_size > 0) if(code->description != NULL && code->description->instruction_size > 0)
return _instruction_fixed(code, ai, operands, operands_cnt); return _instruction_fixed(code, ai, operands, operands_cnt);
return _instruction_variable(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); return _instruction_variable_immediate(code, ai, operand, &value, 0);
} }
#endif #endif
#endif
#if 0 #if 0
switch(AO_GET_SIZE(ai->opcode)) switch(AO_GET_SIZE(ai->opcode))
{ {
@ -655,7 +653,8 @@ int code_open(Code * code, char const * filename)
return -1; return -1;
if((code->fp = fopen(filename, "w+")) == NULL) if((code->fp = fopen(filename, "w+")) == NULL)
return -error_set_code(1, "%s: %s", filename, strerror(errno)); 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); fclose(code->fp);
code->fp = NULL; code->fp = NULL;
@ -676,13 +675,3 @@ int code_section(Code * code, char const * section)
#endif #endif
return format_section(code->format, section); 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);
}

View File

@ -46,8 +46,7 @@ int code_close(Code * code);
ArchInstruction * code_decode(Code * code, char const * buffer, size_t * size); ArchInstruction * code_decode(Code * code, char const * buffer, size_t * size);
int code_function(Code * code, char const * function); int code_function(Code * code, char const * function);
int code_instruction(Code * code, char const * name, AsOperand ** operands, int code_instruction(Code * code, ArchInstructionCall * call);
size_t operands_cnt);
int code_section(Code * code, char const * section); int code_section(Code * code, char const * section);
#endif /* !ASM_CODE_H */ #endif /* !ASM_CODE_H */

View File

@ -30,11 +30,10 @@
/* types */ /* types */
struct _Format struct _Format
{ {
char * name;
char * arch; char * arch;
FormatPluginHelper helper; FormatPluginHelper helper;
FormatPlugin * plugin;
Plugin * handle; Plugin * handle;
FormatPlugin * plugin;
}; };
@ -60,8 +59,8 @@ Format * format_new(char const * format, char const * arch)
plugin_delete(handle); plugin_delete(handle);
return NULL; return NULL;
} }
f->name = string_new(format);
f->arch = string_new(arch); f->arch = string_new(arch);
memset(&f->helper, 0, sizeof(f->helper));
f->plugin = plugin; f->plugin = plugin;
f->handle = handle; f->handle = handle;
if(f->arch == NULL) if(f->arch == NULL)
@ -78,7 +77,6 @@ void format_delete(Format * format)
{ {
plugin_delete(format->handle); plugin_delete(format->handle);
string_delete(format->arch); string_delete(format->arch);
string_delete(format->name);
object_delete(format); object_delete(format);
} }
@ -87,7 +85,7 @@ void format_delete(Format * format)
/* format_get_name */ /* format_get_name */
char const * format_get_name(Format * format) char const * format_get_name(Format * format)
{ {
return format->name; return format->plugin->name;
} }

View File

@ -20,7 +20,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include "Asm/format.h" #include "Asm.h"
/* DEX */ /* DEX */

View File

@ -21,7 +21,7 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <elf.h> #include <elf.h>
#include "Asm/format.h" #include "Asm.h"
/* portability */ /* portability */
#define Elf64_Quarter unsigned char #define Elf64_Quarter unsigned char

View File

@ -19,7 +19,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include "Asm/format.h" #include "Asm.h"
/* Flat */ /* Flat */

View File

@ -22,7 +22,7 @@
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <errno.h> #include <errno.h>
#include "Asm/format.h" #include "Asm.h"
/* Java */ /* Java */

View File

@ -21,7 +21,7 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include "Asm/format.h" #include "Asm.h"
/* PE */ /* PE */

View File

@ -34,9 +34,16 @@ typedef struct _State
unsigned int error_cnt; unsigned int error_cnt;
unsigned int warning_cnt; unsigned int warning_cnt;
Code * code; Code * code;
char * operator; ArchInstructionCall call;
AsOperand ** operands; #if 0
char const * name;
struct
{
ArchOperandDefinition definition;
ArchOperand operand;
} operands[3];
size_t operands_cnt; size_t operands_cnt;
#endif
} State; } State;
@ -209,7 +216,6 @@ int parser(Code * code, char const * infile)
" warning(s)"); " warning(s)");
if(state.token != NULL) if(state.token != NULL)
token_delete(state.token); token_delete(state.token);
free(state.operands);
return state.error_cnt; return state.error_cnt;
} }
@ -386,7 +392,6 @@ static int _instruction(State * state)
/* operator [ space [ operand_list ] ] newline */ /* operator [ space [ operand_list ] ] newline */
{ {
int ret; int ret;
size_t i;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__); fprintf(stderr, "DEBUG: %s()\n", __func__);
@ -398,22 +403,14 @@ static int _instruction(State * state)
if(_parser_in_set(state, TS_OPERAND_LIST)) if(_parser_in_set(state, TS_OPERAND_LIST))
ret |= _operand_list(state); ret |= _operand_list(state);
} }
if(state->operator != NULL) if(state->call.name != NULL)
{ {
if(code_instruction(state->code, state->operator, if(code_instruction(state->code, &state->call) != 0)
state->operands, state->operands_cnt))
ret |= _parser_error(state, "%s", error_get()); ret |= _parser_error(state, "%s", error_get());
free(state->operator); free(state->call.name);
state->operator = NULL;
} }
for(i = 0; i < state->operands_cnt; i++) /* FIXME memory leak (register names...) */
{ memset(&state->call, 0, sizeof(state->call));
free(state->operands[i]->value2);
free(state->operands[i]->value);
free(state->operands[i]);
}
/* optimized free(state->operands); out */
state->operands_cnt = 0;
return ret | _newline(state); return ret | _newline(state);
} }
@ -423,7 +420,6 @@ static int _operator(State * state)
/* WORD */ /* WORD */
{ {
char const * string; char const * string;
char * operator = NULL;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__); fprintf(stderr, "DEBUG: %s()\n", __func__);
@ -433,12 +429,11 @@ static int _operator(State * state)
_parser_scan(state); _parser_scan(state);
return 1; return 1;
} }
if((operator = strdup(string)) == NULL) if((state->call.name = strdup(string)) == NULL)
return error_set_code(1, "%s", strerror(errno)); return error_set_code(1, "%s", strerror(errno));
/* optimized free(state->operator); out */ /* optimized free(state->operator); out */
state->operator = operator;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "%s \"%s\"\n", "DEBUG: operator", operator); fprintf(stderr, "%s \"%s\"\n", "DEBUG: operator", string);
#endif #endif
return _parser_scan(state); return _parser_scan(state);
} }
@ -478,9 +473,7 @@ static int _operand(State * state)
int ret = 0; int ret = 0;
TokenCode code; TokenCode code;
char const * string; char const * string;
AsOperand ** p; ArchOperand * p;
unsigned long * l;
unsigned long * u;
if(state->token == NULL) if(state->token == NULL)
return 1; return 1;
@ -499,22 +492,7 @@ static int _operand(State * state)
fprintf(stderr, "%s%s\"\n", "DEBUG: new operand: \"", fprintf(stderr, "%s%s\"\n", "DEBUG: new operand: \"",
token_get_string(state->token)); token_get_string(state->token));
#endif #endif
if((p = realloc(state->operands, (state->operands_cnt + 1) p = &state->call.operands[state->call.operands_cnt];
* sizeof(*p))) == NULL)
ret |= _parser_error(state, "%s", strerror(errno));
else if((p[state->operands_cnt] = malloc(sizeof(**p))) == NULL)
{
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)) switch(token_get_code(state->token))
{ {
case AS_CODE_OPERATOR_MINUS: case AS_CODE_OPERATOR_MINUS:
@ -523,50 +501,31 @@ static int _operand(State * state)
string = token_get_string(state->token); string = token_get_string(state->token);
if(string == NULL) if(string == NULL)
break; break;
(*p)->operand = AO_IMMEDIATE(AOF_SIGNED, p->type = AOT_IMMEDIATE;
0, 0);
if((l = malloc(sizeof(*l))) == NULL)
{
ret |= _parser_error(state,
"%s", strerror(
errno));
break;
}
/* FIXME also true for numbers? */ /* FIXME also true for numbers? */
*l = -strtoul(string + 1, NULL, 0); p->value.immediate.value = strtoul(string + 1,
(*p)->value = l; NULL, 0);
p->value.immediate.negative = 1;
break; break;
case AS_CODE_IMMEDIATE: case AS_CODE_IMMEDIATE:
case AS_CODE_NUMBER: case AS_CODE_NUMBER:
(*p)->operand = AO_IMMEDIATE(0, 0, 0); p->type = AOT_IMMEDIATE;
if((u = malloc(sizeof(*u))) == NULL)
{
ret |= _parser_error(state,
"%s", strerror(
errno));
break;
}
/* FIXME also true for numbers? */ /* FIXME also true for numbers? */
*u = strtoul(string + 1, NULL, 0); p->value.immediate.value = strtoul(string + 1,
(*p)->value = u; NULL, 0);
break; break;
case AS_CODE_REGISTER: case AS_CODE_REGISTER:
if(code == AS_CODE_OPERATOR_LBRACKET) p->type = (code == AS_CODE_OPERATOR_LBRACKET)
(*p)->operand = AO_DREGISTER(0, ? AOT_DREGISTER : AOT_REGISTER;
0, 0, 0);
else
(*p)->operand = AO_REGISTER(0,
0, 0);
/* FIXME check errors */ /* FIXME check errors */
(*p)->value = strdup(string); p->value._register.name = strdup(string);
break; break;
default: default:
ret |= _parser_error(state, "%s", ret |= _parser_error(state, "%s",
"Expected value"); "Expected value");
break; break;
} }
state->operands_cnt++; state->call.operands_cnt++;
}
} }
ret |= _parser_scan(state); ret |= _parser_scan(state);
if(code == AS_CODE_OPERATOR_LBRACKET) if(code == AS_CODE_OPERATOR_LBRACKET)
@ -574,27 +533,29 @@ static int _operand(State * state)
if(_parser_in_set(state, TS_SPACE)) if(_parser_in_set(state, TS_SPACE))
ret |= _space(state); ret |= _space(state);
/* FIXME implement AS_CODE_OPERATOR_MINUS too */
if(_parser_is_code(state, AS_CODE_OPERATOR_PLUS)) if(_parser_is_code(state, AS_CODE_OPERATOR_PLUS))
{ {
ret |= _parser_scan(state); ret |= _parser_scan(state);
if(_parser_in_set(state, TS_SPACE)) if(_parser_in_set(state, TS_SPACE))
ret |= _space(state); ret |= _space(state);
/* FIXME register or immediate value */ /* XXX this is quite ugly */
p = &state->operands[state->operands_cnt - 1]; /* XXX */ p = &state->call.operands[state->call.operands_cnt - 1];
string = token_get_string(state->token); string = token_get_string(state->token);
switch(token_get_code(state->token)) switch(token_get_code(state->token))
{ {
case AS_CODE_IMMEDIATE: case AS_CODE_IMMEDIATE:
(*p)->operand = AO_DREGISTER(0, 0, 0, p->value.dregister.offset = strtoul(
0); string + 1, NULL, 0);
(*p)->dereference = strtoul(string + 1,
NULL, 0);
break; break;
case AS_CODE_REGISTER: case AS_CODE_REGISTER:
/* FIXME check everything... */ /* FIXME check everything... */
(*p)->operand = AO_DREGISTER2(0, 0, 0, p->type = AOT_DREGISTER2;
0); p->value.dregister2.name2 = strdup(
(*p)->value2 = strdup(string); string);
break;
default:
/* FIXME report an error */
break; break;
} }
ret |= _parser_scan(state); ret |= _parser_scan(state);