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
|
||||
# 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 */
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
175
src/arch.c
175
src/arch.c
@ -25,12 +25,18 @@
|
||||
#include "arch.h"
|
||||
#include "../config.h"
|
||||
|
||||
/* macros */
|
||||
#ifndef abs
|
||||
# define abs(a) ((a) >= 0 ? (a) : -(a))
|
||||
#endif
|
||||
|
||||
|
||||
/* Arch */
|
||||
/* private */
|
||||
/* types */
|
||||
struct _Arch
|
||||
{
|
||||
ArchPluginHelper helper;
|
||||
Plugin * handle;
|
||||
ArchPlugin * plugin;
|
||||
size_t instructions_cnt;
|
||||
@ -66,6 +72,7 @@ Arch * arch_new(char const * name)
|
||||
plugin_delete(handle);
|
||||
return NULL;
|
||||
}
|
||||
memset(&a->helper, 0, sizeof(a->helper));
|
||||
a->handle = handle;
|
||||
a->plugin = plugin;
|
||||
a->instructions_cnt = 0;
|
||||
@ -99,8 +106,9 @@ ArchDescription * arch_get_description(Arch * arch)
|
||||
/* arch_get_format */
|
||||
char const * arch_get_format(Arch * arch)
|
||||
{
|
||||
if(arch->plugin->format != NULL)
|
||||
return arch->plugin->format;
|
||||
if(arch->plugin->description != NULL
|
||||
&& arch->plugin->description->format != NULL)
|
||||
return arch->plugin->description->format;
|
||||
return "elf";
|
||||
}
|
||||
|
||||
@ -144,7 +152,7 @@ ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size,
|
||||
ai = &arch->plugin->instructions[i];
|
||||
if(AO_GET_SIZE(ai->opcode) != size)
|
||||
continue;
|
||||
if(ai->value == opcode)
|
||||
if(ai->opcode == opcode)
|
||||
return ai;
|
||||
}
|
||||
#if 0
|
||||
@ -162,17 +170,18 @@ ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size,
|
||||
}
|
||||
|
||||
|
||||
/* arch_get_instruction_by_operands */
|
||||
static int _operands_operands(Arch * arch, ArchInstruction * ai,
|
||||
AsOperand ** operands, size_t operands_cnt);
|
||||
static int _operands_operands_dregister(Arch * arch, uint32_t operand,
|
||||
AsOperand * aso);
|
||||
static int _operands_operands_immediate(uint32_t operand, AsOperand * aso);
|
||||
static int _operands_operands_register(Arch * arch, uint32_t operand,
|
||||
AsOperand * aso);
|
||||
/* arch_get_instruction_by_call */
|
||||
static int _call_operands(Arch * arch, ArchInstruction * ai,
|
||||
ArchInstructionCall * call);
|
||||
static int _call_operands_dregister(Arch * arch,
|
||||
ArchOperandDefinition definition, ArchOperand * operand);
|
||||
static int _call_operands_immediate(ArchOperandDefinition definition,
|
||||
ArchOperand * operand);
|
||||
static int _call_operands_register(Arch * arch,
|
||||
ArchOperandDefinition definition, ArchOperand * operand);
|
||||
|
||||
ArchInstruction * arch_get_instruction_by_operands(Arch * arch,
|
||||
char const * name, AsOperand ** operands, size_t operands_cnt)
|
||||
ArchInstruction * arch_get_instruction_by_call(Arch * arch,
|
||||
ArchInstructionCall * call)
|
||||
{
|
||||
size_t i;
|
||||
ArchInstruction * ai;
|
||||
@ -185,50 +194,51 @@ ArchInstruction * arch_get_instruction_by_operands(Arch * arch,
|
||||
{
|
||||
ai = &arch->plugin->instructions[i];
|
||||
/* FIXME use a (sorted) hash table */
|
||||
if(strcmp(ai->name, name) != 0)
|
||||
if(strcmp(ai->name, call->name) != 0)
|
||||
continue;
|
||||
found = 1;
|
||||
if(_operands_operands(arch, ai, operands, operands_cnt) == 0)
|
||||
if(_call_operands(arch, ai, call) == 0)
|
||||
return ai;
|
||||
}
|
||||
error_set_code(1, "%s \"%s\"", found ? "Invalid arguments to"
|
||||
: "Unknown instruction", name);
|
||||
: "Unknown instruction", call->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _operands_operands(Arch * arch, ArchInstruction * ai,
|
||||
AsOperand ** operands, size_t operands_cnt)
|
||||
static int _call_operands(Arch * arch, ArchInstruction * ai,
|
||||
ArchInstructionCall * call)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t operand;
|
||||
ArchOperandDefinition definition;
|
||||
ArchOperand * operand;
|
||||
|
||||
for(i = 0; i < operands_cnt; i++)
|
||||
for(i = 0; i < call->operands_cnt; i++)
|
||||
{
|
||||
if(i >= 3)
|
||||
return -1;
|
||||
operand = (i == 0) ? ai->op1 : ((i == 1) ? ai->op2 : ai->op3);
|
||||
definition = (i == 0) ? ai->op1 : ((i == 1) ? ai->op2
|
||||
: ai->op3);
|
||||
operand = &call->operands[i];
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() operand %lu, type %u, type %u\n",
|
||||
__func__, i, AO_GET_TYPE(operand),
|
||||
AO_GET_TYPE(operands[i]->operand));
|
||||
__func__, i, AO_GET_TYPE(definition),
|
||||
AO_GET_TYPE(operand->definition));
|
||||
#endif
|
||||
if(AO_GET_TYPE(operand) != AO_GET_TYPE(operands[i]->operand))
|
||||
if(AO_GET_TYPE(definition) != operand->type)
|
||||
return -1;
|
||||
switch(AO_GET_TYPE(operand))
|
||||
switch(AO_GET_TYPE(definition))
|
||||
{
|
||||
case AOT_IMMEDIATE:
|
||||
if(_operands_operands_immediate(operand,
|
||||
operands[i]) != 0)
|
||||
if(_call_operands_immediate(definition, operand)
|
||||
!= 0)
|
||||
return -1;
|
||||
break;
|
||||
case AOT_DREGISTER:
|
||||
if(_operands_operands_dregister(arch, operand,
|
||||
operands[i]) != 0)
|
||||
if(_call_operands_dregister(arch, definition,
|
||||
operand) != 0)
|
||||
return -1;
|
||||
break;
|
||||
case AOT_REGISTER:
|
||||
if(_operands_operands_register(arch, operand,
|
||||
operands[i]) != 0)
|
||||
if(_call_operands_register(arch, definition,
|
||||
operand) != 0)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
@ -236,56 +246,48 @@ static int _operands_operands(Arch * arch, ArchInstruction * ai,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _operands_operands_dregister(Arch * arch, uint32_t operand,
|
||||
AsOperand * aso)
|
||||
static int _call_operands_dregister(Arch * arch,
|
||||
ArchOperandDefinition definition, ArchOperand * operand)
|
||||
{
|
||||
unsigned long dereference;
|
||||
unsigned long max;
|
||||
uint64_t offset;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() %ld\n", __func__, aso->dereference);
|
||||
fprintf(stderr, "DEBUG: %s() %ld\n", __func__, ao->dereference);
|
||||
#endif
|
||||
if(_operands_operands_register(arch, operand, aso) != 0)
|
||||
if(_call_operands_register(arch, definition, operand) != 0)
|
||||
return -1;
|
||||
if(aso->dereference == 0)
|
||||
/* check if there is an offset applied */
|
||||
if(operand->value.dregister.offset == 0)
|
||||
return 0;
|
||||
dereference = (aso->dereference > 0) ? aso->dereference
|
||||
: -aso->dereference;
|
||||
/* check if the size fits */
|
||||
max = 1;
|
||||
max <<= AO_GET_DSIZE(operand);
|
||||
if(dereference > max - 1)
|
||||
/* check if the offset fits */
|
||||
offset = abs(operand->value.dregister.offset);
|
||||
offset >>= AO_GET_DSIZE(definition);
|
||||
if(offset > 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _operands_operands_immediate(uint32_t operand, AsOperand * aso)
|
||||
static int _call_operands_immediate(ArchOperandDefinition definition,
|
||||
ArchOperand * operand)
|
||||
{
|
||||
unsigned long value;
|
||||
long lvalue;
|
||||
unsigned long max;
|
||||
uint64_t value;
|
||||
uint32_t size;
|
||||
|
||||
/* check if the size fits */
|
||||
if(AO_GET_FLAGS(operand) & AOF_SIGNED)
|
||||
{
|
||||
lvalue = *(unsigned long*)aso->value;
|
||||
value = (lvalue >= 0) ? lvalue : -lvalue;
|
||||
}
|
||||
else
|
||||
value = *(unsigned long*)aso->value;
|
||||
/* apply negative offset */
|
||||
if(AO_GET_FLAGS(operand) & AOF_SOFFSET)
|
||||
value >>= AO_GET_OFFSET(operand);
|
||||
max = 1;
|
||||
max <<= AO_GET_SIZE(operand);
|
||||
if(value > max - 1)
|
||||
value = operand->value.immediate.value;
|
||||
if((size = AO_GET_SIZE(definition)) > 0
|
||||
&& AO_GET_FLAGS(definition) & AOF_SIGNED)
|
||||
size--;
|
||||
value >>= size;
|
||||
if(value > 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _operands_operands_register(Arch * arch, uint32_t operand,
|
||||
AsOperand * aso)
|
||||
static int _call_operands_register(Arch * arch,
|
||||
ArchOperandDefinition definition, ArchOperand * operand)
|
||||
{
|
||||
char const * name = operand->value._register.name;
|
||||
ArchDescription * desc;
|
||||
uint32_t size;
|
||||
ArchRegister * ar;
|
||||
@ -295,14 +297,13 @@ static int _operands_operands_register(Arch * arch, uint32_t operand,
|
||||
&& desc->instruction_size != 0)
|
||||
size = desc->instruction_size;
|
||||
else
|
||||
size = AO_GET_SIZE(operand);
|
||||
size = AO_GET_SIZE(definition);
|
||||
/* check if it exists */
|
||||
if((ar = arch_get_register_by_name_size(arch, aso->value, size))
|
||||
== NULL)
|
||||
if((ar = arch_get_register_by_name_size(arch, name, size)) == NULL)
|
||||
return -1;
|
||||
/* for implicit instructions it must match */
|
||||
if(AO_GET_FLAGS(operand) & AOF_IMPLICIT
|
||||
&& AO_GET_VALUE(operand) != ar->id)
|
||||
if(AO_GET_FLAGS(definition) & AOF_IMPLICIT
|
||||
&& AO_GET_VALUE(definition) != ar->id)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
@ -370,16 +371,34 @@ ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name,
|
||||
|
||||
|
||||
/* useful */
|
||||
/* arch_filter */
|
||||
int arch_filter(Arch * arch, ArchInstruction * instruction, ArchOperand operand,
|
||||
unsigned char * buf, size_t size)
|
||||
/* arch_exit */
|
||||
int arch_exit(Arch * arch)
|
||||
{
|
||||
memset(&arch->helper, 0, sizeof(arch->helper));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* arch_init */
|
||||
int arch_init(Arch * arch, char const * filename, FILE * fp)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s(\"%s\", %p)\n", __func__, filename,
|
||||
(void *)fp);
|
||||
#endif
|
||||
arch->helper.filename = filename;
|
||||
arch->helper.fp = fp;
|
||||
arch->plugin->helper = &arch->helper;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* arch_write */
|
||||
int arch_write(Arch * arch, ArchInstruction * instruction,
|
||||
ArchInstructionCall * call)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, instruction->name);
|
||||
#endif
|
||||
if(arch->plugin->filter == NULL)
|
||||
return -error_set_code(1, "%s: %s", arch->plugin->name,
|
||||
"Instruction filter required but not defined");
|
||||
return arch->plugin->filter(arch->plugin, instruction, operand, buf,
|
||||
size);
|
||||
return arch->plugin->write(arch->plugin, instruction, call);
|
||||
}
|
||||
|
13
src/arch.h
13
src/arch.h
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
21
src/asm.c
21
src/asm.c
@ -194,23 +194,24 @@ int as_function(As * as, char const * name)
|
||||
/* as_instruction */
|
||||
int as_instruction(As * as, char const * name, unsigned int operands_cnt, ...)
|
||||
{
|
||||
int ret;
|
||||
ArchInstructionCall call;
|
||||
va_list ap;
|
||||
AsOperand ** ao = NULL;
|
||||
size_t i;
|
||||
ArchOperand * operand;
|
||||
|
||||
if(operands_cnt != 0)
|
||||
memset(&call, 0, sizeof(call));
|
||||
call.name = name;
|
||||
if((call.operands_cnt = operands_cnt) != 0)
|
||||
{
|
||||
if((ao = malloc(sizeof(*ao) * operands_cnt)) == NULL)
|
||||
return error_set_code(1, "%s", strerror(errno));
|
||||
va_start(ap, operands_cnt);
|
||||
for(i = 0; i < operands_cnt; i++)
|
||||
ao[i] = va_arg(ap, AsOperand *);
|
||||
for(i = 0; i < 3 && i < operands_cnt; i++)
|
||||
{
|
||||
operand = va_arg(ap, ArchOperand *);
|
||||
memcpy(&call.operands[i], operand, sizeof(*operand));
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
ret = code_instruction(as->code, name, ao, operands_cnt);
|
||||
free(ao);
|
||||
return ret;
|
||||
return code_instruction(as->code, &call);
|
||||
}
|
||||
|
||||
|
||||
|
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 */
|
||||
/* 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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "Asm/format.h"
|
||||
#include "Asm.h"
|
||||
|
||||
|
||||
/* DEX */
|
||||
|
@ -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
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "Asm/format.h"
|
||||
#include "Asm.h"
|
||||
|
||||
|
||||
/* Flat */
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include "Asm/format.h"
|
||||
#include "Asm.h"
|
||||
|
||||
|
||||
/* Java */
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include "Asm/format.h"
|
||||
#include "Asm.h"
|
||||
|
||||
|
||||
/* PE */
|
||||
|
159
src/parser.c
159
src/parser.c
@ -34,9 +34,16 @@ typedef struct _State
|
||||
unsigned int error_cnt;
|
||||
unsigned int warning_cnt;
|
||||
Code * code;
|
||||
char * operator;
|
||||
AsOperand ** operands;
|
||||
ArchInstructionCall call;
|
||||
#if 0
|
||||
char const * name;
|
||||
struct
|
||||
{
|
||||
ArchOperandDefinition definition;
|
||||
ArchOperand operand;
|
||||
} operands[3];
|
||||
size_t operands_cnt;
|
||||
#endif
|
||||
} State;
|
||||
|
||||
|
||||
@ -209,7 +216,6 @@ int parser(Code * code, char const * infile)
|
||||
" warning(s)");
|
||||
if(state.token != NULL)
|
||||
token_delete(state.token);
|
||||
free(state.operands);
|
||||
return state.error_cnt;
|
||||
}
|
||||
|
||||
@ -386,7 +392,6 @@ static int _instruction(State * state)
|
||||
/* operator [ space [ operand_list ] ] newline */
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
@ -398,22 +403,14 @@ static int _instruction(State * state)
|
||||
if(_parser_in_set(state, TS_OPERAND_LIST))
|
||||
ret |= _operand_list(state);
|
||||
}
|
||||
if(state->operator != NULL)
|
||||
if(state->call.name != NULL)
|
||||
{
|
||||
if(code_instruction(state->code, state->operator,
|
||||
state->operands, state->operands_cnt))
|
||||
if(code_instruction(state->code, &state->call) != 0)
|
||||
ret |= _parser_error(state, "%s", error_get());
|
||||
free(state->operator);
|
||||
state->operator = NULL;
|
||||
free(state->call.name);
|
||||
}
|
||||
for(i = 0; i < state->operands_cnt; i++)
|
||||
{
|
||||
free(state->operands[i]->value2);
|
||||
free(state->operands[i]->value);
|
||||
free(state->operands[i]);
|
||||
}
|
||||
/* optimized free(state->operands); out */
|
||||
state->operands_cnt = 0;
|
||||
/* FIXME memory leak (register names...) */
|
||||
memset(&state->call, 0, sizeof(state->call));
|
||||
return ret | _newline(state);
|
||||
}
|
||||
|
||||
@ -423,7 +420,6 @@ static int _operator(State * state)
|
||||
/* WORD */
|
||||
{
|
||||
char const * string;
|
||||
char * operator = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s()\n", __func__);
|
||||
@ -433,12 +429,11 @@ static int _operator(State * state)
|
||||
_parser_scan(state);
|
||||
return 1;
|
||||
}
|
||||
if((operator = strdup(string)) == NULL)
|
||||
if((state->call.name = strdup(string)) == NULL)
|
||||
return error_set_code(1, "%s", strerror(errno));
|
||||
/* optimized free(state->operator); out */
|
||||
state->operator = operator;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "%s \"%s\"\n", "DEBUG: operator", operator);
|
||||
fprintf(stderr, "%s \"%s\"\n", "DEBUG: operator", string);
|
||||
#endif
|
||||
return _parser_scan(state);
|
||||
}
|
||||
@ -478,9 +473,7 @@ static int _operand(State * state)
|
||||
int ret = 0;
|
||||
TokenCode code;
|
||||
char const * string;
|
||||
AsOperand ** p;
|
||||
unsigned long * l;
|
||||
unsigned long * u;
|
||||
ArchOperand * p;
|
||||
|
||||
if(state->token == NULL)
|
||||
return 1;
|
||||
@ -499,74 +492,40 @@ static int _operand(State * state)
|
||||
fprintf(stderr, "%s%s\"\n", "DEBUG: new operand: \"",
|
||||
token_get_string(state->token));
|
||||
#endif
|
||||
if((p = realloc(state->operands, (state->operands_cnt + 1)
|
||||
* sizeof(*p))) == NULL)
|
||||
ret |= _parser_error(state, "%s", strerror(errno));
|
||||
else if((p[state->operands_cnt] = malloc(sizeof(**p))) == NULL)
|
||||
p = &state->call.operands[state->call.operands_cnt];
|
||||
switch(token_get_code(state->token))
|
||||
{
|
||||
state->operands = p;
|
||||
ret |= _parser_error(state, "%s", strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
state->operands = p;
|
||||
p = &state->operands[state->operands_cnt];
|
||||
(*p)->operand = 0;
|
||||
(*p)->dereference = 0;
|
||||
(*p)->value = NULL;
|
||||
(*p)->value2 = NULL;
|
||||
switch(token_get_code(state->token))
|
||||
{
|
||||
case AS_CODE_OPERATOR_MINUS:
|
||||
ret |= _parser_scan(state);
|
||||
/* FIXME check if a number */
|
||||
string = token_get_string(state->token);
|
||||
if(string == NULL)
|
||||
break;
|
||||
(*p)->operand = AO_IMMEDIATE(AOF_SIGNED,
|
||||
0, 0);
|
||||
if((l = malloc(sizeof(*l))) == NULL)
|
||||
{
|
||||
ret |= _parser_error(state,
|
||||
"%s", strerror(
|
||||
errno));
|
||||
break;
|
||||
}
|
||||
/* FIXME also true for numbers? */
|
||||
*l = -strtoul(string + 1, NULL, 0);
|
||||
(*p)->value = l;
|
||||
break;
|
||||
case AS_CODE_IMMEDIATE:
|
||||
case AS_CODE_NUMBER:
|
||||
(*p)->operand = AO_IMMEDIATE(0, 0, 0);
|
||||
if((u = malloc(sizeof(*u))) == NULL)
|
||||
{
|
||||
ret |= _parser_error(state,
|
||||
"%s", strerror(
|
||||
errno));
|
||||
break;
|
||||
}
|
||||
/* FIXME also true for numbers? */
|
||||
*u = strtoul(string + 1, NULL, 0);
|
||||
(*p)->value = u;
|
||||
break;
|
||||
case AS_CODE_REGISTER:
|
||||
if(code == AS_CODE_OPERATOR_LBRACKET)
|
||||
(*p)->operand = AO_DREGISTER(0,
|
||||
0, 0, 0);
|
||||
else
|
||||
(*p)->operand = AO_REGISTER(0,
|
||||
0, 0);
|
||||
/* FIXME check errors */
|
||||
(*p)->value = strdup(string);
|
||||
break;
|
||||
default:
|
||||
ret |= _parser_error(state, "%s",
|
||||
"Expected value");
|
||||
break;
|
||||
}
|
||||
state->operands_cnt++;
|
||||
case AS_CODE_OPERATOR_MINUS:
|
||||
ret |= _parser_scan(state);
|
||||
/* FIXME check if a number */
|
||||
string = token_get_string(state->token);
|
||||
if(string == NULL)
|
||||
break;
|
||||
p->type = AOT_IMMEDIATE;
|
||||
/* FIXME also true for numbers? */
|
||||
p->value.immediate.value = strtoul(string + 1,
|
||||
NULL, 0);
|
||||
p->value.immediate.negative = 1;
|
||||
break;
|
||||
case AS_CODE_IMMEDIATE:
|
||||
case AS_CODE_NUMBER:
|
||||
p->type = AOT_IMMEDIATE;
|
||||
/* FIXME also true for numbers? */
|
||||
p->value.immediate.value = strtoul(string + 1,
|
||||
NULL, 0);
|
||||
break;
|
||||
case AS_CODE_REGISTER:
|
||||
p->type = (code == AS_CODE_OPERATOR_LBRACKET)
|
||||
? AOT_DREGISTER : AOT_REGISTER;
|
||||
/* FIXME check errors */
|
||||
p->value._register.name = strdup(string);
|
||||
break;
|
||||
default:
|
||||
ret |= _parser_error(state, "%s",
|
||||
"Expected value");
|
||||
break;
|
||||
}
|
||||
state->call.operands_cnt++;
|
||||
}
|
||||
ret |= _parser_scan(state);
|
||||
if(code == AS_CODE_OPERATOR_LBRACKET)
|
||||
@ -574,27 +533,29 @@ static int _operand(State * state)
|
||||
|
||||
if(_parser_in_set(state, TS_SPACE))
|
||||
ret |= _space(state);
|
||||
/* FIXME implement AS_CODE_OPERATOR_MINUS too */
|
||||
if(_parser_is_code(state, AS_CODE_OPERATOR_PLUS))
|
||||
{
|
||||
ret |= _parser_scan(state);
|
||||
if(_parser_in_set(state, TS_SPACE))
|
||||
ret |= _space(state);
|
||||
/* FIXME register or immediate value */
|
||||
p = &state->operands[state->operands_cnt - 1]; /* XXX */
|
||||
/* XXX this is quite ugly */
|
||||
p = &state->call.operands[state->call.operands_cnt - 1];
|
||||
string = token_get_string(state->token);
|
||||
switch(token_get_code(state->token))
|
||||
{
|
||||
case AS_CODE_IMMEDIATE:
|
||||
(*p)->operand = AO_DREGISTER(0, 0, 0,
|
||||
0);
|
||||
(*p)->dereference = strtoul(string + 1,
|
||||
NULL, 0);
|
||||
p->value.dregister.offset = strtoul(
|
||||
string + 1, NULL, 0);
|
||||
break;
|
||||
case AS_CODE_REGISTER:
|
||||
/* FIXME check everything... */
|
||||
(*p)->operand = AO_DREGISTER2(0, 0, 0,
|
||||
0);
|
||||
(*p)->value2 = strdup(string);
|
||||
p->type = AOT_DREGISTER2;
|
||||
p->value.dregister2.name2 = strdup(
|
||||
string);
|
||||
break;
|
||||
default:
|
||||
/* FIXME report an error */
|
||||
break;
|
||||
}
|
||||
ret |= _parser_scan(state);
|
||||
|
Loading…
Reference in New Issue
Block a user