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
# 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/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 */

View File

@ -19,9 +19,10 @@
# define DEVEL_ASM_ARCH_H
# include <stdint.h>
# include <stdio.h>
/* 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 */

View File

@ -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;

View File

@ -18,15 +18,10 @@
#ifndef 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>
/* 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 */

View File

@ -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);
}

View File

@ -18,8 +18,8 @@
#ifndef ASM_ARCH_H
# define ASM_ARCH_H
# include <sys/types.h>
# include <stdint.h>
# include <stdio.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_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 */

View File

@ -16,10 +16,8 @@
#include <stddef.h>
#ifdef DEBUG
# include <stdio.h>
#endif
#include "Asm/arch.h"
#include <string.h>
#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;
}

View File

@ -16,13 +16,13 @@
#include <stddef.h>
#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;
}

View File

@ -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 */

View File

@ -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);
}

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 */
/* 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);
}

View File

@ -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 */

View File

@ -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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);