Created
November 4, 2016 07:44
-
-
Save vuonghv/44dc334f3e116e32cc58d7a18b921fc3 to your computer and use it in GitHub Desktop.
Defining New Types using Python's C API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* pydasm -- Python module wrapping libdasm | |
* 2016 Vuong Hoang <[email protected]> | |
*/ | |
#include <Python.h> | |
#include <structmember.h> | |
#include "../libdasm.h" | |
#define INSTRUCTION_STR_BUFFER_LENGTH 256 | |
// Support Python 2.5 | |
#ifndef PyVarObject_HEAD_INIT | |
#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, | |
#endif | |
#ifndef Py_TYPE | |
#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) | |
#endif | |
/* | |
* Instruction types borrowed from "libdasm.h" | |
*/ | |
char *instruction_types[] = { | |
"INSTRUCTION_TYPE_ASC", | |
"INSTRUCTION_TYPE_DCL", | |
"INSTRUCTION_TYPE_MOV", | |
"INSTRUCTION_TYPE_MOVSR", | |
"INSTRUCTION_TYPE_ADD", | |
"INSTRUCTION_TYPE_XADD", | |
"INSTRUCTION_TYPE_ADC", | |
"INSTRUCTION_TYPE_SUB", | |
"INSTRUCTION_TYPE_SBB", | |
"INSTRUCTION_TYPE_INC", | |
"INSTRUCTION_TYPE_DEC", | |
"INSTRUCTION_TYPE_DIV", | |
"INSTRUCTION_TYPE_IDIV", | |
"INSTRUCTION_TYPE_NOT", | |
"INSTRUCTION_TYPE_NEG", | |
"INSTRUCTION_TYPE_STOS", | |
"INSTRUCTION_TYPE_LODS", | |
"INSTRUCTION_TYPE_SCAS", | |
"INSTRUCTION_TYPE_MOVS", | |
"INSTRUCTION_TYPE_MOVSX", | |
"INSTRUCTION_TYPE_MOVZX", | |
"INSTRUCTION_TYPE_CMPS", | |
"INSTRUCTION_TYPE_SHX", | |
"INSTRUCTION_TYPE_ROX", | |
"INSTRUCTION_TYPE_MUL", | |
"INSTRUCTION_TYPE_IMUL", | |
"INSTRUCTION_TYPE_EIMUL", | |
"INSTRUCTION_TYPE_XOR", | |
"INSTRUCTION_TYPE_LEA", | |
"INSTRUCTION_TYPE_XCHG", | |
"INSTRUCTION_TYPE_CMP", | |
"INSTRUCTION_TYPE_TEST", | |
"INSTRUCTION_TYPE_PUSH", | |
"INSTRUCTION_TYPE_AND", | |
"INSTRUCTION_TYPE_OR", | |
"INSTRUCTION_TYPE_POP", | |
"INSTRUCTION_TYPE_JMP", | |
"INSTRUCTION_TYPE_JMPC", | |
"INSTRUCTION_TYPE_JECXZ", | |
"INSTRUCTION_TYPE_SETC", | |
"INSTRUCTION_TYPE_MOVC", | |
"INSTRUCTION_TYPE_LOOP", | |
"INSTRUCTION_TYPE_CALL", | |
"INSTRUCTION_TYPE_RET", | |
"INSTRUCTION_TYPE_ENTER", | |
"INSTRUCTION_TYPE_INT", | |
"INSTRUCTION_TYPE_BT", | |
"INSTRUCTION_TYPE_BTS", | |
"INSTRUCTION_TYPE_BTR", | |
"INSTRUCTION_TYPE_BTC", | |
"INSTRUCTION_TYPE_BSF", | |
"INSTRUCTION_TYPE_BSR", | |
"INSTRUCTION_TYPE_BSWAP", | |
"INSTRUCTION_TYPE_SGDT", | |
"INSTRUCTION_TYPE_SIDT", | |
"INSTRUCTION_TYPE_SLDT", | |
"INSTRUCTION_TYPE_LFP", | |
"INSTRUCTION_TYPE_CLD", | |
"INSTRUCTION_TYPE_STD", | |
"INSTRUCTION_TYPE_XLAT", | |
"INSTRUCTION_TYPE_FCMOVC", | |
"INSTRUCTION_TYPE_FADD", | |
"INSTRUCTION_TYPE_FADDP", | |
"INSTRUCTION_TYPE_FIADD", | |
"INSTRUCTION_TYPE_FSUB", | |
"INSTRUCTION_TYPE_FSUBP", | |
"INSTRUCTION_TYPE_FISUB", | |
"INSTRUCTION_TYPE_FSUBR", | |
"INSTRUCTION_TYPE_FSUBRP", | |
"INSTRUCTION_TYPE_FISUBR", | |
"INSTRUCTION_TYPE_FMUL", | |
"INSTRUCTION_TYPE_FMULP", | |
"INSTRUCTION_TYPE_FIMUL", | |
"INSTRUCTION_TYPE_FDIV", | |
"INSTRUCTION_TYPE_FDIVP", | |
"INSTRUCTION_TYPE_FDIVR", | |
"INSTRUCTION_TYPE_FDIVRP", | |
"INSTRUCTION_TYPE_FIDIV", | |
"INSTRUCTION_TYPE_FIDIVR", | |
"INSTRUCTION_TYPE_FCOM", | |
"INSTRUCTION_TYPE_FCOMP", | |
"INSTRUCTION_TYPE_FCOMPP", | |
"INSTRUCTION_TYPE_FCOMI", | |
"INSTRUCTION_TYPE_FCOMIP", | |
"INSTRUCTION_TYPE_FUCOM", | |
"INSTRUCTION_TYPE_FUCOMP", | |
"INSTRUCTION_TYPE_FUCOMPP", | |
"INSTRUCTION_TYPE_FUCOMI", | |
"INSTRUCTION_TYPE_FUCOMIP", | |
"INSTRUCTION_TYPE_FST", | |
"INSTRUCTION_TYPE_FSTP", | |
"INSTRUCTION_TYPE_FIST", | |
"INSTRUCTION_TYPE_FISTP", | |
"INSTRUCTION_TYPE_FISTTP", | |
"INSTRUCTION_TYPE_FLD", | |
"INSTRUCTION_TYPE_FILD", | |
"INSTRUCTION_TYPE_FICOM", | |
"INSTRUCTION_TYPE_FICOMP", | |
"INSTRUCTION_TYPE_FFREE", | |
"INSTRUCTION_TYPE_FFREEP", | |
"INSTRUCTION_TYPE_FXCH", | |
"INSTRUCTION_TYPE_SYSENTER", | |
"INSTRUCTION_TYPE_FPU_CTRL", | |
"INSTRUCTION_TYPE_FPU", | |
"INSTRUCTION_TYPE_MMX", | |
"INSTRUCTION_TYPE_SSE", | |
"INSTRUCTION_TYPE_OTHER", | |
"INSTRUCTION_TYPE_PRIV", | |
NULL | |
}; | |
/* | |
* Operand types borrowed from "libdasm.h" | |
*/ | |
char *operand_types[] = { | |
"OPERAND_TYPE_NONE", | |
"OPERAND_TYPE_MEMORY", | |
"OPERAND_TYPE_REGISTER", | |
"OPERAND_TYPE_IMMEDIATE", | |
NULL | |
}; | |
/* | |
* Registers borrowed from "libdasm.h" | |
*/ | |
char *registers[] = { | |
"REGISTER_EAX", | |
"REGISTER_ECX", | |
"REGISTER_EDX", | |
"REGISTER_EBX", | |
"REGISTER_ESP", | |
"REGISTER_EBP", | |
"REGISTER_ESI", | |
"REGISTER_EDI", | |
"REGISTER_NOP", | |
NULL | |
}; | |
/* | |
* Register types borrowed from "libdasm.h" | |
*/ | |
char *register_types[] = { | |
"REGISTER_TYPE_GEN", | |
"REGISTER_TYPE_SEGMENT", | |
"REGISTER_TYPE_DEBUG", | |
"REGISTER_TYPE_CONTROL", | |
"REGISTER_TYPE_TEST", | |
"REGISTER_TYPE_XMM", | |
"REGISTER_TYPE_MMX", | |
"REGISTER_TYPE_FPU", | |
NULL | |
}; | |
/* | |
* Define INST class | |
*/ | |
typedef struct { | |
PyObject_HEAD | |
unsigned long type; // Instruction type and flags | |
const char *mnemonic; // Instruction mnemonic | |
int flags1; // First operand flags (if any) | |
int flags2; // Second operand flags (if any) | |
int flags3; // Additional operand flags (if any) | |
int modrm; // Is MODRM byte present? | |
short eflags_affected; // Processor eflags affected | |
short eflags_used; // Processor eflags used by this instruction | |
int iop_written; // mask of affected implied registers (written) | |
int iop_read; // mask of affected implied registers (read) | |
} INSTObject; | |
static void INSTObject_dealloc(INSTObject *self) | |
{ | |
Py_TYPE(self)->tp_free((PyObject *)self); | |
} | |
static int INSTObject_init(INSTObject *self, PyObject *args, PyObject *kwds) | |
{ | |
static char *kwlist[] = { | |
"type", "mnemonic", "flags1", "flags2", "flags3", "modrm", | |
"eflags_affected", "eflags_used", "iop_written", "iop_read", | |
NULL | |
}; | |
const char *format = "|ksiiiihhii"; | |
int success = PyArg_ParseTupleAndKeywords( | |
args, kwds, format, kwlist, | |
&self->type, &self->mnemonic, &self->flags1, &self->flags2, | |
&self->flags3, &self->modrm, &self->eflags_affected, | |
&self->eflags_used, &self->iop_written, &self->iop_read | |
); | |
if (!success) { | |
return -1; | |
} | |
return 0; | |
} | |
static PyMemberDef INSTObject_members[] = { | |
{"type", T_ULONG, offsetof(INSTObject, type), 0, "Instruction type"}, | |
{"mnemonic", T_STRING, offsetof(INSTObject, mnemonic), 0, "Instruction mnemonic"}, | |
{"flags1", T_INT, offsetof(INSTObject, flags1), 0, "First operand flags"}, | |
{"flags2", T_INT, offsetof(INSTObject, flags2), 0, "Second operand flags"}, | |
{"flags3", T_INT, offsetof(INSTObject, flags3), 0, "Additional operand flags"}, | |
{"modrm", T_INT, offsetof(INSTObject, modrm), 0, "Is MODRM byte present?"}, | |
{"eflags_affected", T_SHORT, offsetof(INSTObject, eflags_affected), 0, | |
"Processor eflags affected"}, | |
{"eflags_used", T_SHORT, offsetof(INSTObject, eflags_used), 0, | |
"Processor eflags used by this instruction"}, | |
{"iop_written", T_INT, offsetof(INSTObject, iop_written), 0, | |
"mask of affected implied registers"}, | |
{"iop_read", T_INT, offsetof(INSTObject, iop_read), 0, | |
"mask of affected implied registers"}, | |
{NULL} /* Sentinel */ | |
}; | |
// TODO: Use C99 Structure initialization | |
static PyTypeObject INSTType = { | |
PyVarObject_HEAD_INIT(NULL, 0) | |
"pydasm.INST", /* tp_name */ | |
sizeof(INSTObject), /* tp_basicsize */ | |
0, /* tp_itemsize */ | |
(destructor)INSTObject_dealloc, /* tp_dealloc */ | |
0, /* tp_print */ | |
0, /* tp_getattr */ | |
0, /* tp_setattr */ | |
0, /* tp_reserved */ | |
0, /* tp_repr */ | |
0, /* tp_as_number */ | |
0, /* tp_as_sequence */ | |
0, /* tp_as_mapping */ | |
0, /* tp_hash */ | |
0, /* tp_call */ | |
0, /* tp_str */ | |
0, /* tp_getattro */ | |
0, /* tp_setattro */ | |
0, /* tp_as_buffer */ | |
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
"INST objects", /* tp_doc */ | |
0, /* tp_traverse */ | |
0, /* tp_clear */ | |
0, /* tp_richcompare */ | |
0, /* tp_weaklistoffset */ | |
0, /* tp_iter */ | |
0, /* tp_iternext */ | |
0, /* tp_methods */ | |
INSTObject_members, /* tp_members */ | |
0, /* tp_getset */ | |
0, /* tp_base */ | |
0, /* tp_dict */ | |
0, /* tp_descr_get */ | |
0, /* tp_descr_set */ | |
0, /* tp_dictoffset */ | |
(initproc)INSTObject_init, /* tp_init */ | |
0, /* tp_alloc */ | |
PyType_GenericNew, /* tp_new */ | |
}; | |
/* | |
* Define Operand for the instruction | |
*/ | |
typedef struct { | |
PyObject_HEAD | |
int type; // Operand type (register, memory, etc) | |
int reg; // Register (if any) | |
int basereg; // Base register (if any) | |
int indexreg; // Index register (if any) | |
int scale; // Scale (if any) | |
int dispbytes; // Displacement bytes (0 = no displacement) | |
int dispoffset; // Displacement value offset | |
int immbytes; // Immediate bytes (0 = no immediate) | |
int immoffset; // Immediate value offset | |
int sectionbytes; // Section prefix bytes (0 = no section prefix) | |
unsigned int section; // Section prefix value | |
unsigned long displacement; // Displacement value | |
unsigned long immediate; // Immediate value | |
int flags; // Operand flags | |
} OPERANDObject; | |
static void OPERANDObject_dealloc(OPERANDObject *self) | |
{ | |
Py_TYPE(self)->tp_free((PyObject *)self); | |
} | |
static int | |
OPERANDObject_init(OPERANDObject *self, PyObject *args, PyObject *kwds) | |
{ | |
static char *kwlist[] = { | |
"type", "reg", "basereg", "indexreg", "scale", | |
"dispbytes", "dispoffset", "immbytes", "immoffset", | |
"sectionbytes", "section", "displacement", "immediate", "flags", | |
NULL | |
}; | |
const char *format = "|iiiiiiiiiiIkki"; | |
int success = PyArg_ParseTupleAndKeywords( | |
args, kwds, format, kwlist, | |
&self->type, &self->reg, &self->basereg, &self->indexreg, | |
&self->scale, &self->dispbytes, &self->dispoffset, | |
&self->immbytes, &self->immoffset, &self->sectionbytes, | |
&self->section, &self->displacement, &self->immediate, | |
&self->flags | |
); | |
if (!success) { | |
return -1; | |
} | |
return 0; | |
} | |
static PyMemberDef OPERANDObject_members[] = { | |
{"type", T_INT, offsetof(OPERANDObject, type), 0, | |
"Operand type (register, memory, etc)"}, | |
{"reg", T_INT, offsetof(OPERANDObject, reg), 0, "Register"}, | |
{"basereg", T_INT, offsetof(OPERANDObject, basereg), 0, "Base register"}, | |
{"indexreg", T_INT, offsetof(OPERANDObject, indexreg), 0, "Index register"}, | |
{"scale", T_INT, offsetof(OPERANDObject, scale), 0, "Scale"}, | |
{"dispbytes", T_INT, offsetof(OPERANDObject, dispbytes), 0, | |
"Displacement bytes (0 = no displacement)"}, | |
{"dispoffset", T_INT, offsetof(OPERANDObject, dispoffset), 0, | |
"Displacement value offset"}, | |
{"immbytes", T_INT, offsetof(OPERANDObject, immbytes), 0, | |
"Immediate bytes (0 = no immediate)"}, | |
{"immoffset", T_INT, offsetof(OPERANDObject, immoffset), 0, | |
"Immediate value offset"}, | |
{"sectionbytes", T_INT, offsetof(OPERANDObject, sectionbytes), 0, | |
"Section prefix bytes (0 = no section prefix)"}, | |
{"section", T_UINT, offsetof(OPERANDObject, section), 0, | |
"Section prefix value"}, | |
{"displacement", T_ULONG, offsetof(OPERANDObject, displacement), 0, | |
"Displacement value"}, | |
{"immediate", T_ULONG, offsetof(OPERANDObject, immediate), 0, | |
"Immediate value"}, | |
{"flags", T_INT, offsetof(OPERANDObject, flags), 0, "Operand flags"}, | |
{NULL} /* Sentinel */ | |
}; | |
// TODO: Use C99 Structure initialization | |
static PyTypeObject OPERANDType = { | |
PyVarObject_HEAD_INIT(NULL, 0) | |
"pydasm.OPERAND", /* tp_name */ | |
sizeof(OPERANDObject), /* tp_basicsize */ | |
0, /* tp_itemsize */ | |
(destructor)OPERANDObject_dealloc, /* tp_dealloc */ | |
0, /* tp_print */ | |
0, /* tp_getattr */ | |
0, /* tp_setattr */ | |
0, /* tp_reserved */ | |
0, /* tp_repr */ | |
0, /* tp_as_number */ | |
0, /* tp_as_sequence */ | |
0, /* tp_as_mapping */ | |
0, /* tp_hash */ | |
0, /* tp_call */ | |
0, /* tp_str */ | |
0, /* tp_getattro */ | |
0, /* tp_setattro */ | |
0, /* tp_as_buffer */ | |
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
"OPERAND objects", /* tp_doc */ | |
0, /* tp_traverse */ | |
0, /* tp_clear */ | |
0, /* tp_richcompare */ | |
0, /* tp_weaklistoffset */ | |
0, /* tp_iter */ | |
0, /* tp_iternext */ | |
0, /* tp_methods */ | |
OPERANDObject_members, /* tp_members */ | |
0, /* tp_getset */ | |
0, /* tp_base */ | |
0, /* tp_dict */ | |
0, /* tp_descr_get */ | |
0, /* tp_descr_set */ | |
0, /* tp_dictoffset */ | |
(initproc)OPERANDObject_init, /* tp_init */ | |
0, /* tp_alloc */ | |
PyType_GenericNew, /* tp_new */ | |
}; | |
/* | |
* Define INSTRUCTION class | |
*/ | |
typedef struct { | |
PyObject_HEAD | |
int length; // Instruction length | |
int type; // Instruction type | |
int mode; // Addressing mode | |
unsigned int opcode; // Actual opcode | |
unsigned int modrm; // MODRM byte | |
unsigned int sib; // SIB byte | |
int modrm_offset; // MODRM byte offset | |
int extindex; // Extension table index | |
int fpuindex; // FPU table index | |
int dispbytes; // Displacement bytes (0 = no displacement) | |
int immbytes; // Immediate bytes (0 = no immediate) | |
int sectionbytes; // Section prefix bytes (0 = no section prefix) | |
PyObject *op1; // First operand (if any) | |
PyObject *op2; // Second operand (if any) | |
PyObject *op3; // Additional operand (if any) | |
PyObject *ptr; // Pointer to instruction table | |
int flags; // Instruction flags | |
short eflags_affected; // Process eflags affected | |
short eflags_used; // Processor eflags used by this instruction | |
int iop_written; // mask of affected implied registers (written) | |
int iop_read; // mask of affected implied registers (read) | |
} INSTRUCTIONObject; | |
static void INSTRUCTIONObject_dealloc(INSTRUCTIONObject *self) | |
{ | |
Py_XDECREF(self->op1); | |
Py_XDECREF(self->op2); | |
Py_XDECREF(self->op3); | |
Py_XDECREF(self->ptr); | |
Py_TYPE(self)->tp_free((PyObject *)self); | |
} | |
static int | |
INSTRUCTIONObject_init(INSTRUCTIONObject *self, PyObject *args, PyObject *kwds) | |
{ | |
PyObject *op1 = NULL; | |
PyObject *op2 = NULL; | |
PyObject *op3 = NULL; | |
PyObject *ptr = NULL; | |
PyObject *tmp = NULL; | |
static char *kwlist[] = { | |
"length", "type", "mode", "opcode", "modrm", "sib", "modrm_offset", | |
"extindex", "fpuindex", "dispbytes", "immbytes", "sectionbytes", | |
"op1", "op2", "op3", "ptr", "flags", "eflags_affected", | |
"eflags_used", "iop_written", "iop_read" | |
}; | |
static char *format = "iiiIIIiiiiiiOOOOihhii"; | |
int success = PyArg_ParseTupleAndKeywords( | |
args, kwds, format, kwlist, | |
&self->length, &self->type, &self->mode, &self->opcode, | |
&self->modrm, &self->sib, &self->modrm_offset, &self->extindex, | |
&self->fpuindex, &self->dispbytes, &self->immbytes, | |
&self->sectionbytes, &op1, &op2, &op3, &ptr, &self->flags, | |
&self->eflags_affected, &self->eflags_used, | |
&self->iop_written, &self->iop_read | |
); | |
if (!success) { | |
return -1; | |
} | |
if (op1) { | |
tmp = self->op1; | |
Py_INCREF(op1); | |
self->op1 = op1; | |
Py_XDECREF(tmp); | |
} | |
if (op2) { | |
tmp = self->op2; | |
Py_INCREF(op2); | |
self->op2 = op2; | |
Py_XDECREF(tmp); | |
} | |
if (op3) { | |
tmp = self->op3; | |
Py_INCREF(op3); | |
self->op3 = op3; | |
Py_XDECREF(tmp); | |
} | |
if (ptr) { | |
tmp = self->ptr; | |
Py_INCREF(ptr); | |
self->ptr = ptr; | |
Py_XDECREF(tmp); | |
} | |
return 0; | |
} | |
static PyMemberDef INSTRUCTIONObject_memebers[] = { | |
{"length", T_INT, offsetof(INSTRUCTIONObject, length), 0, "Instruction length"}, | |
{"type", T_INT, offsetof(INSTRUCTIONObject, type), 0, "Instruction type"}, | |
{"mode", T_INT, offsetof(INSTRUCTIONObject, mode), 0, "Addressing mode"}, | |
{"opcode", T_UINT, offsetof(INSTRUCTIONObject, opcode), 0, "Actual opcode"}, | |
{"modrm", T_UINT, offsetof(INSTRUCTIONObject, modrm), 0, "MODRM byte"}, | |
{"sib", T_UINT, offsetof(INSTRUCTIONObject, sib), 0, "SIB byte"}, | |
{"modrm_offset", T_INT, offsetof(INSTRUCTIONObject, modrm_offset), 0, "MODRM byte offset"}, | |
{"extindex", T_INT, offsetof(INSTRUCTIONObject, extindex), 0, "Extension table index"}, | |
{"fpuindex", T_INT, offsetof(INSTRUCTIONObject, fpuindex), 0, "FPU table index"}, | |
{"dispbytes", T_INT, offsetof(INSTRUCTIONObject, dispbytes), 0, | |
"Displacement bytes (0 = no displacement)"}, | |
{"immbytes", T_INT, offsetof(INSTRUCTIONObject, immbytes), 0, | |
"Immediate bytes (0 = no immediate)"}, | |
{"sectionbytes", T_INT, offsetof(INSTRUCTIONObject, sectionbytes), 0, | |
"Section prefix bytes (0 = no section prefix)"}, | |
{"op1", T_OBJECT, offsetof(INSTRUCTIONObject, op1), 0, "First operand"}, | |
{"op2", T_OBJECT, offsetof(INSTRUCTIONObject, op2), 0, "Second operand"}, | |
{"op3", T_OBJECT, offsetof(INSTRUCTIONObject, op3), 0, "Additional operand"}, | |
{"ptr", T_OBJECT, offsetof(INSTRUCTIONObject, ptr), 0, "Instruction table"}, | |
{"flags", T_INT, offsetof(INSTRUCTIONObject, flags), 0, "Instruction flags"}, | |
{"eflags_affected", T_SHORT, offsetof(INSTRUCTIONObject, eflags_affected), 0, | |
"Process eflags effected"}, | |
{"eflags_used", T_SHORT, offsetof(INSTRUCTIONObject, eflags_used), 0, | |
"Process eflags used by this instruction"}, | |
{"iop_written", T_INT, offsetof(INSTRUCTIONObject, iop_written), 0, | |
"mask of affected implied registers (written)"}, | |
{"iop_read", T_INT, offsetof(INSTRUCTIONObject, iop_read), 0, | |
"mask of affected implied registers (read)"}, | |
{NULL} /* Sentinel */ | |
}; | |
// TODO: Use C99 Structure initialization | |
static PyTypeObject INSTRUCTIONType = { | |
PyVarObject_HEAD_INIT(NULL, 0) | |
"pydasm.INSTRUCTION", /* tp_name */ | |
sizeof(INSTRUCTIONObject), /* tp_basicsize */ | |
0, /* tp_itemsize */ | |
(destructor)INSTRUCTIONObject_dealloc, /* tp_dealloc */ | |
0, /* tp_print */ | |
0, /* tp_getattr */ | |
0, /* tp_setattr */ | |
0, /* tp_reserved */ | |
0, /* tp_repr */ | |
0, /* tp_as_number */ | |
0, /* tp_as_sequence */ | |
0, /* tp_as_mapping */ | |
0, /* tp_hash */ | |
0, /* tp_call */ | |
0, /* tp_str */ | |
0, /* tp_getattro */ | |
0, /* tp_setattro */ | |
0, /* tp_as_buffer */ | |
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ | |
"INSTRUCTION objects", /* tp_doc */ | |
0, /* tp_traverse */ | |
0, /* tp_clear */ | |
0, /* tp_richcompare */ | |
0, /* tp_weaklistoffset */ | |
0, /* tp_iter */ | |
0, /* tp_iternext */ | |
0, /* tp_methods */ | |
INSTRUCTIONObject_memebers, /* tp_members */ | |
0, /* tp_getset */ | |
0, /* tp_base */ | |
0, /* tp_dict */ | |
0, /* tp_descr_get */ | |
0, /* tp_descr_set */ | |
0, /* tp_dictoffset */ | |
(initproc)INSTRUCTIONObject_init, /* tp_init */ | |
0, /* tp_alloc */ | |
PyType_GenericNew, /* tp_new */ | |
}; | |
/* | |
* For module init | |
*/ | |
static PyModuleDef pydasm_module = { | |
PyModuleDef_HEAD_INIT, | |
"pydasm", | |
"Python module wrapping libdasm", | |
-1, | |
NULL, NULL, NULL, NULL, NULL | |
}; | |
PyMODINIT_FUNC PyInit_pydasm(void) | |
{ | |
int i; | |
PyObject *m; | |
if (PyType_Ready(&INSTType) < 0) { | |
return NULL; | |
} | |
if (PyType_Ready(&OPERANDType) < 0) { | |
return NULL; | |
} | |
if (PyType_Ready(&INSTRUCTIONType) < 0) { | |
return NULL; | |
} | |
m = PyModule_Create(&pydasm_module); | |
if (m == NULL) { | |
return NULL; | |
} | |
Py_INCREF(&INSTType); | |
PyModule_AddObject(m, "INST", (PyObject *)&INSTType); | |
Py_INCREF(&OPERANDType); | |
PyModule_AddObject(m, "OPERAND", (PyObject *)&OPERANDType); | |
Py_INCREF(&INSTRUCTIONType); | |
PyModule_AddObject(m, "INSTRUCTION", (PyObject *)&INSTRUCTIONType); | |
PyModule_AddIntMacro(m, FORMAT_ATT); | |
PyModule_AddIntMacro(m, FORMAT_INTEL); | |
PyModule_AddIntMacro(m, MODE_16); | |
PyModule_AddIntMacro(m, MODE_32); | |
/* | |
* TODO: test code | |
* class LAVA(object): | |
* pass | |
* | |
*/ | |
PyObject *pClassName = PyUnicode_FromString("VALA"); | |
PyObject *pClassBase = PyTuple_New(1); | |
PyTuple_SetItem(pClassBase, 0, (PyObject *)&PyBaseObject_Type); | |
PyObject *pClassDict = PyDict_New(); | |
PyObject *args = PyTuple_New(3); | |
PyTuple_SetItem(args, 0, pClassName); | |
PyTuple_SetItem(args, 1, pClassBase); | |
PyTuple_SetItem(args, 2, pClassDict); | |
PyObject *lava = PyObject_CallObject((PyObject *)&PyType_Type, args); | |
PyModule_AddObject(m, "lava", lava); | |
Py_DECREF(pClassName); | |
Py_DECREF(pClassBase); | |
Py_DECREF(pClassDict); | |
Py_DECREF(args); | |
// end test | |
for (i = 0; instruction_types[i]; ++i) { | |
PyModule_AddIntConstant(m, instruction_types[i], i); | |
} | |
for (i = 0; operand_types[i]; ++i) { | |
PyModule_AddIntConstant(m, operand_types[i], i); | |
} | |
for (i = 0; registers[i]; ++i) { | |
PyModule_AddIntConstant(m, registers[i], i); | |
} | |
for (i = 0; register_types[i]; ++i) { | |
PyModule_AddIntConstant(m, register_types[i], i); | |
} | |
return m; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
wchar_t *program = Py_DecodeLocale(argv[0], NULL); | |
if (program == NULL) { | |
fprintf(stderr, "Fatal error: cannot decode argv[0]\n"); | |
exit(EXIT_FAILURE); | |
} | |
Py_SetProgramName(program); | |
Py_Initialize(); | |
PyInit_pydasm(); | |
PyMem_RawFree(program); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment