Letting each plug-in output instructions as it pleases
This commit is contained in:
parent
77f32dfab2
commit
95834007bc
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
175
src/arch.c
175
src/arch.c
@ -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);
|
|
||||||
}
|
}
|
||||||
|
13
src/arch.h
13
src/arch.h
@ -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 */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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 */
|
||||||
|
21
src/asm.c
21
src/asm.c
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
51
src/code.c
51
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 */
|
/* 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);
|
|
||||||
}
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
|
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
@ -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 */
|
||||||
|
159
src/parser.c
159
src/parser.c
@ -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,74 +492,40 @@ 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)
|
switch(token_get_code(state->token))
|
||||||
ret |= _parser_error(state, "%s", strerror(errno));
|
|
||||||
else if((p[state->operands_cnt] = malloc(sizeof(**p))) == NULL)
|
|
||||||
{
|
{
|
||||||
state->operands = p;
|
case AS_CODE_OPERATOR_MINUS:
|
||||||
ret |= _parser_error(state, "%s", strerror(errno));
|
ret |= _parser_scan(state);
|
||||||
}
|
/* FIXME check if a number */
|
||||||
else
|
string = token_get_string(state->token);
|
||||||
{
|
if(string == NULL)
|
||||||
state->operands = p;
|
break;
|
||||||
p = &state->operands[state->operands_cnt];
|
p->type = AOT_IMMEDIATE;
|
||||||
(*p)->operand = 0;
|
/* FIXME also true for numbers? */
|
||||||
(*p)->dereference = 0;
|
p->value.immediate.value = strtoul(string + 1,
|
||||||
(*p)->value = NULL;
|
NULL, 0);
|
||||||
(*p)->value2 = NULL;
|
p->value.immediate.negative = 1;
|
||||||
switch(token_get_code(state->token))
|
break;
|
||||||
{
|
case AS_CODE_IMMEDIATE:
|
||||||
case AS_CODE_OPERATOR_MINUS:
|
case AS_CODE_NUMBER:
|
||||||
ret |= _parser_scan(state);
|
p->type = AOT_IMMEDIATE;
|
||||||
/* FIXME check if a number */
|
/* FIXME also true for numbers? */
|
||||||
string = token_get_string(state->token);
|
p->value.immediate.value = strtoul(string + 1,
|
||||||
if(string == NULL)
|
NULL, 0);
|
||||||
break;
|
break;
|
||||||
(*p)->operand = AO_IMMEDIATE(AOF_SIGNED,
|
case AS_CODE_REGISTER:
|
||||||
0, 0);
|
p->type = (code == AS_CODE_OPERATOR_LBRACKET)
|
||||||
if((l = malloc(sizeof(*l))) == NULL)
|
? AOT_DREGISTER : AOT_REGISTER;
|
||||||
{
|
/* FIXME check errors */
|
||||||
ret |= _parser_error(state,
|
p->value._register.name = strdup(string);
|
||||||
"%s", strerror(
|
break;
|
||||||
errno));
|
default:
|
||||||
break;
|
ret |= _parser_error(state, "%s",
|
||||||
}
|
"Expected value");
|
||||||
/* FIXME also true for numbers? */
|
break;
|
||||||
*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++;
|
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user