Migrate the pyc plugin ##arch

This commit is contained in:
pancake 2023-03-29 16:56:31 +02:00 committed by pancake
parent 1e2c75cf65
commit a8143d8fb2
47 changed files with 77 additions and 99 deletions

View File

@ -44,7 +44,7 @@ arch.pic
anal.ppc_cs
anal.ppc_gnu
arch.propeller
anal.pyc
arch.pyc
arch.riscv_cs
anal.s390_cs
anal.s390_gnu

View File

@ -54,7 +54,7 @@ arch.snes
arch.riscv
arch.riscv_cs
arch.pic
anal.pyc
arch.pyc
arch.propeller
arch.null
arch.i4004

View File

@ -42,7 +42,7 @@ arch.6502
arch.snes
arch.riscv
arch.pic
anal.pyc
arch.pyc
arch.propeller
esil.dummy
asm.null

View File

@ -31,7 +31,7 @@ arch.riscv
arch.riscv_cs
arch.pic
arch.wasm
anal.pyc
arch.pyc
arch.null
arch.rsp
arch.i4004

View File

@ -3,7 +3,7 @@ arch.x86_nz
arch.arm
anal.dalvik
arch.wasm
anal.pyc
arch.pyc
anal.bf
arch.bpf
arch.riscv

View File

@ -77,7 +77,6 @@ r_anal_sources = [
'p/anal_null.c',
'p/anal_ppc_cs.c',
'p/anal_ppc_gnu.c',
'p/anal_pyc.c',
'p/anal_s390_cs.c',
'p/anal_s390_gnu.c',
'../asm/arch/s390/gnu/s390-dis.c',
@ -122,11 +121,6 @@ r_anal_sources = [
'../asm/arch/tms320/c55x_plus/decode_funcs.c',
'../asm/arch/tms320/c55x_plus/hashtable.c',
'../asm/arch/tms320/c55x_plus/utils.c',
'../asm/arch/pyc/opcode_all.c',
'../asm/arch/pyc/opcode_anal.c',
'../asm/arch/pyc/opcode_arg_fmt.c',
'../asm/arch/pyc/opcode.c',
'../asm/arch/pyc/pyc_dis.c'
]
incdirs = [
'arch'

View File

@ -1,17 +0,0 @@
PYC_ASM_ROOT=../../asm/arch/pyc/
OBJ_PYC=anal_pyc.o
OBJ_PYC+=$(PYC_ASM_ROOT)/opcode_all.o
OBJ_PYC+=$(PYC_ASM_ROOT)/opcode_anal.o
OBJ_PYC+=$(PYC_ASM_ROOT)/opcode_arg_fmt.o
OBJ_PYC+=$(PYC_ASM_ROOT)/opcode.o
OBJ_PYC+=$(PYC_ASM_ROOT)/pyc_dis.o
STATIC_OBJ+=$(OBJ_PYC)
TARGET_PYC=anal_pyc.$(EXT_SO)
ALL_TARGETS+=$(TARGET_PYC)
PYC_ROOT=../asm/arch/pyc
CFLAGS+=-I$(PYC_ROOT)
$(TARGET_PYC): $(OBJ_PYC)
$(CC) $(call libname,anal_pyc) $(CFLAGS) $(LDFLAGS) -o $(TARGET_PYC) $(OBJ_PYC) -lr_util

View File

@ -85,6 +85,13 @@ r_arch_sources = [
'p/ebc/ebc_disas.c',
'p/msp430/plugin.c',
'p/msp430/msp430_disas.c',
# python
'p/pyc/plugin.c',
'p/pyc/opcode_all.c',
'p/pyc/opcode_anal.c',
'p/pyc/opcode_arg_fmt.c',
'p/pyc/opcode.c',
'p/pyc/pyc_dis.c'
]
if arch_plugins.contains('x86_nz')

15
libr/arch/p/pyc.mk Normal file
View File

@ -0,0 +1,15 @@
PYC_ROOT=p/pyc
OBJ_PYC=p/pyc/plugin.o
OBJ_PYC+=$(PYC_ROOT)/opcode_all.o
OBJ_PYC+=$(PYC_ROOT)/opcode_anal.o
OBJ_PYC+=$(PYC_ROOT)/opcode_arg_fmt.o
OBJ_PYC+=$(PYC_ROOT)/opcode.o
OBJ_PYC+=$(PYC_ROOT)/pyc_dis.o
STATIC_OBJ+=$(OBJ_PYC)
TARGET_PYC=arch_pyc.$(EXT_SO)
ALL_TARGETS+=$(TARGET_PYC)
$(TARGET_PYC): $(OBJ_PYC)
$(CC) $(call libname,arch_pyc) $(CFLAGS) $(LDFLAGS) -o $(TARGET_PYC) $(OBJ_PYC) -lr_util

View File

@ -1,45 +1,38 @@
/* radare - LGPL3 - Copyright 2016-2022 - FXTi */
/* radare - LGPL3 - Copyright 2016-2023 - FXTi, pancake */
#include <r_lib.h>
#include <r_anal.h>
#include "../../asm/arch/pyc/pyc_dis.h"
static R_TH_LOCAL pyc_opcodes *ops = NULL;
static int disassemble(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
RList *shared = NULL;
RBin *bin = a->binb.bin;
#include <r_arch.h>
#include "pyc_dis.h"
static bool disassemble(RArchSession *s, RAnalOp *op, RArchDecodeMask mask) {
RBin *bin = s->arch->binb.bin;
RBinPlugin *plugin = bin && bin->cur && bin->cur->o? bin->cur->o->plugin: NULL;
if (plugin) {
if (!strcmp (plugin->name, "pyc")) {
shared = bin->cur->o->bin_obj;
}
}
RList *shared = (plugin && !strcmp (plugin->name, "pyc"))?
bin->cur->o->bin_obj: NULL;
RList *cobjs = NULL;
RList *interned_table = NULL;
if (shared) {
cobjs = r_list_get_n (shared, 0);
interned_table = r_list_get_n (shared, 1);
}
if (!ops || !pyc_opcodes_equal (ops, a->config->cpu)) {
ops = get_opcode_by_version (a->config->cpu);
pyc_opcodes *ops = s->data;
if (!ops || !pyc_opcodes_equal (ops, s->config->cpu)) {
ops = get_opcode_by_version (s->config->cpu);
if (!ops) {
ops = get_opcode_by_version ("v3.9.0");
if (!ops) {
return 0;
return false;
}
}
ops->bits = a->config->bits;
ops->bits = s->config->bits;
}
int r = r_pyc_disasm (op, buf, cobjs, interned_table, addr, ops);
s->data = ops;
int r = r_pyc_disasm (op, op->bytes, cobjs, interned_table, op->addr, ops);
op->size = r;
return r;
return r > 0;
}
static int archinfo(RAnal *anal, int query) {
static int archinfo(RArchSession *anal, ut32 query) {
switch (query) {
case R_ANAL_ARCHINFO_MIN_OP_SIZE:
return (anal->config->bits == 16)? 1: 2;
@ -50,7 +43,7 @@ static int archinfo(RAnal *anal, int query) {
}
}
static char *get_reg_profile(RAnal *anal) {
static char *regs(RArchSession *as) {
return strdup (
"=PC pc\n"
"=BP bp\n"
@ -71,68 +64,59 @@ static char *get_reg_profile(RAnal *anal) {
);
}
static bool set_reg_profile(RAnal *anal) {
char *rp = get_reg_profile (anal);
if (rp) {
bool b = r_reg_set_profile_string (anal->reg, rp);
free (rp);
return b;
}
return false;
}
static RList *get_pyc_code_obj(RAnal *anal) {
RBin *b = anal->binb.bin;
static RList *get_pyc_code_obj(RArchSession *as) {
RBin *b = as->arch->binb.bin;
RBinPlugin *plugin = b->cur && b->cur->o? b->cur->o->plugin: NULL;
bool is_pyc = (plugin && strcmp (plugin->name, "pyc") == 0);
return is_pyc? b->cur->o->bin_obj: NULL;
}
static int pyc_op(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask) {
RList *pyobj = get_pyc_code_obj (a);
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
RList *pyobj = get_pyc_code_obj (as);
if (!pyobj) {
return -1;
return false;
}
const ut64 addr = op->addr;
const ut8 *data = op->bytes;
RList *cobjs = r_list_get_n (pyobj, 0);
RListIter *iter = NULL;
pyc_code_object *func = NULL, *t = NULL;
r_list_foreach (cobjs, iter, t) {
if (R_BETWEEN (t->start_offset, addr, t->end_offset - 1)) { // addr in [start_offset, end_offset)
if (R_BETWEEN (t->start_offset, addr, t->end_offset - 1)) {
func = t;
break;
}
}
if (!func) {
return -1;
return false;
}
if (mask & R_ARCH_OP_MASK_DISASM) {
disassemble (a, op, addr, data, len);
disassemble (as, op, mask);
}
ut64 func_base = func->start_offset;
ut32 extended_arg = 0, oparg = 0;
ut8 op_code = data[0];
op->addr = addr;
op->sign = true;
op->type = R_ANAL_OP_TYPE_ILL;
op->id = op_code;
if (!ops || !pyc_opcodes_equal (ops, a->config->cpu)) {
if (!(ops = get_opcode_by_version (a->config->cpu))) {
return -1;
pyc_opcodes *ops = as->data;
if (!ops || !pyc_opcodes_equal (ops, as->config->cpu)) {
if (!(ops = get_opcode_by_version (as->config->cpu))) {
return false;
}
}
int bits = a->config->bits;
const int bits = as->config->bits;
bool is_python36 = bits == 8;
pyc_opcode_object *op_obj = &ops->opcodes[op_code];
if (!op_obj->op_name) {
op->type = R_ANAL_OP_TYPE_ILL;
op->size = 1;
goto anal_end;
goto beach;
}
op->size = is_python36? 2: ((op_code >= ops->have_argument)? 3: 1);
if (op_code >= ops->have_argument) {
if (!is_python36) {
oparg = data[1] + data[2] * 256 + extended_arg;
@ -149,7 +133,7 @@ static int pyc_op(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *data, int len, RA
op->type = R_ANAL_OP_TYPE_CJMP;
op->fail = addr + ((is_python36)? 2: 3);
}
goto anal_end;
goto beach;
}
if (op_obj->type & HASJREL) {
op->type = R_ANAL_OP_TYPE_JMP;
@ -160,47 +144,42 @@ static int pyc_op(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *data, int len, RA
op->type = R_ANAL_OP_TYPE_CJMP;
//op->fail = addr + ((is_python36)? 2: 3);
}
//goto anal_end;
}
if (op_obj->type & HASCOMPARE) {
op->type = R_ANAL_OP_TYPE_CMP;
goto anal_end;
goto beach;
}
anal_pyc_op (op, op_obj, oparg);
anal_end:
//free_opcode (ops);
return op->size;
beach:
return op->size > 0;
}
static int finish(void *user) {
static bool finish(RArchSession *s) {
pyc_opcodes *ops = s->data;
if (ops) {
free_opcode (ops);
ops = NULL;
s->data = NULL;
}
return 0;
return true;
}
RAnalPlugin r_anal_plugin_pyc = {
RArchPlugin r_arch_plugin_pyc = {
.name = "pyc",
.desc = "Python bytecode analysis plugin",
.license = "LGPL3",
.arch = "pyc",
.bits = 32,
.archinfo = archinfo,
.get_reg_profile = get_reg_profile,
.set_reg_profile = &set_reg_profile,
.op = &pyc_op,
.esil = false,
.bits = R_SYS_BITS_PACK1 (32),
.info = archinfo,
.regs = regs,
.decode = &decode,
.fini = &finish,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.data = &r_anal_plugin_pyc,
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_pyc,
.version = R2_VERSION
};
#endif

View File

@ -1594,7 +1594,6 @@ extern RAnalPlugin r_anal_plugin_x86_im;
extern RAnalPlugin r_anal_plugin_x86_simple;
extern RAnalPlugin r_anal_plugin_x86_udis;
extern RAnalPlugin r_anal_plugin_xcore_cs;
extern RAnalPlugin r_anal_plugin_pyc;
extern RAnalPlugin r_anal_plugin_pickle;
extern RAnalPlugin r_anal_plugin_evm_cs;
extern RAnalPlugin r_anal_plugin_hppa_gnu;

View File

@ -325,6 +325,7 @@ extern RArchPlugin r_arch_plugin_pdp11;
extern RArchPlugin r_arch_plugin_lh5801;
extern RArchPlugin r_arch_plugin_ebc;
extern RArchPlugin r_arch_plugin_msp430;
extern RArchPlugin r_arch_plugin_pyc;
#ifdef __cplusplus
}

View File

@ -7,6 +7,7 @@ asm_plugins = [ 'null' ]
anal_plugins = [ 'null' ]
arch_plugins = [ 'null',
# 'arc',
'pyc',
'lh5801',
'ebc',
'msp430',
@ -152,7 +153,6 @@ endif
# else
if no_user_plugins
# TODO: add the pyc plugin for meson builds too
anal_plugins += [
'6502_cs',
'8051',