rizin/librz/asm/arch/pyc/opcode.c
2022-05-02 13:22:12 +02:00

336 lines
9.3 KiB
C

// SPDX-FileCopyrightText: 2020 FXTi <zjxiang1998@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include "opcode.h"
static version_opcode version_op[] = {
{ "1.0.1", opcode_10 },
{ "1.1", opcode_11 },
{ "1.2", opcode_12 },
{ "1.3b1", opcode_13 },
{ "1.4", opcode_14 },
{ "1.4b1", opcode_14 },
{ "1.5a1", opcode_15 },
{ "1.6a2", opcode_16 },
{ "2.0b1", opcode_20 },
{ "2.1a1", opcode_21 },
{ "2.1a2", opcode_21 },
{ "2.2a0", opcode_22 },
{ "2.2a1", opcode_22 },
{ "2.3a0", opcode_23 },
{ "2.4a0", opcode_24 },
{ "2.4a2", opcode_24 },
{ "2.4a3", opcode_24 },
{ "2.5a0", opcode_25 },
{ "2.5b2", opcode_25 },
{ "2.5c3", opcode_25 },
{ "2.6a0", opcode_26 },
{ "2.6a1+", opcode_26 },
{ "2.7a0", opcode_27 },
{ "2.7a2+", opcode_27 },
{ "3.0a1", opcode_30 },
{ "3.0a1+", opcode_30 },
{ "3.0a2", opcode_30 },
{ "3.0a2+", opcode_30 },
{ "3.0a3+", opcode_30 },
{ "3.0a5+", opcode_30 },
{ "3.0x", opcode_30 },
{ "3.1a0", opcode_31 },
{ "3.2a0", opcode_32 },
{ "3.2a1+", opcode_32 },
{ "3.2a2+", opcode_33 },
{ "3.3.0a0", opcode_33 },
{ "3.3.0a1+", opcode_33 },
{ "3.3.0a3+", opcode_33 },
{ "3.3a0", opcode_33 },
{ "3.4.0a0", opcode_34 },
{ "3.4.0a3+", opcode_34 },
{ "3.4.0rc1+", opcode_34 },
{ "3.5.0a0", opcode_35 },
{ "3.5.0a4+", opcode_35 },
{ "3.5.0b1+", opcode_35 },
{ "3.5.0b2+", opcode_35 },
{ "3.6.0a0", opcode_36 },
{ "v3.6.0", opcode_36 },
{ "v3.6.0a2", opcode_36 },
{ "v3.6.0a3", opcode_36 },
{ "v3.6.0a4", opcode_36 },
{ "v3.6.0b1", opcode_36 },
{ "v3.6.0b2", opcode_36 },
{ "v3.6.0b3", opcode_36 },
{ "v3.6.0b4", opcode_36 },
{ "v3.6.0rc1", opcode_36 },
{ "v3.6.0rc2", opcode_36 },
{ "v3.6.1", opcode_36 },
{ "v3.6.10", opcode_36 },
{ "v3.6.10rc", opcode_36 },
{ "v3.6.1rc1", opcode_36 },
{ "v3.6.2", opcode_36 },
{ "v3.6.2rc1", opcode_36 },
{ "v3.6.2rc2", opcode_36 },
{ "v3.6.3", opcode_36 },
{ "v3.6.3rc1", opcode_36 },
{ "v3.6.4", opcode_36 },
{ "v3.6.4rc1", opcode_36 },
{ "v3.6.5", opcode_36 },
{ "v3.6.5rc1", opcode_36 },
{ "v3.6.6", opcode_36 },
{ "v3.6.6rc1", opcode_36 },
{ "v3.6.7", opcode_36 },
{ "v3.6.7rc1", opcode_36 },
{ "v3.6.7rc2", opcode_36 },
{ "v3.6.8", opcode_36 },
{ "v3.6.8rc1", opcode_36 },
{ "v3.6.9", opcode_36 },
{ "v3.6.9rc1", opcode_36 },
{ "v3.7.0", opcode_37 },
{ "v3.7.0a1", opcode_37 },
{ "v3.7.0a2", opcode_37 },
{ "v3.7.0a3", opcode_37 },
{ "v3.7.0a4", opcode_37 },
{ "v3.7.0b1", opcode_37 },
{ "v3.7.0b2", opcode_37 },
{ "v3.7.0b3", opcode_37 },
{ "v3.7.0b4", opcode_37 },
{ "v3.7.0b5", opcode_37 },
{ "v3.7.0rc1", opcode_37 },
{ "v3.7.1", opcode_37 },
{ "v3.7.1rc1", opcode_37 },
{ "v3.7.1rc2", opcode_37 },
{ "v3.7.2", opcode_37 },
{ "v3.7.2rc1", opcode_37 },
{ "v3.7.3", opcode_37 },
{ "v3.7.3rc1", opcode_37 },
{ "v3.7.4", opcode_37 },
{ "v3.7.4rc1", opcode_37 },
{ "v3.7.4rc2", opcode_37 },
{ "v3.7.5", opcode_37 },
{ "v3.7.5rc1", opcode_37 },
{ "v3.7.6", opcode_37 },
{ "v3.7.6rc1", opcode_37 },
{ "v3.8.0", opcode_38 },
{ "v3.8.0a1", opcode_38 },
{ "v3.8.0a2", opcode_38 },
{ "v3.8.0a3", opcode_38 },
{ "v3.8.0a4", opcode_38 },
{ "v3.8.0b1", opcode_38 },
{ "v3.8.0b2", opcode_38 },
{ "v3.8.0b3", opcode_38 },
{ "v3.8.0b4", opcode_38 },
{ "v3.8.0rc1", opcode_38 },
{ "v3.8.1", opcode_38 },
{ "v3.8.1rc1", opcode_38 },
{ "v3.9.0a1", opcode_39 },
{ "v3.9.0a2", opcode_39 },
{ "v3.9.0a3", opcode_39 },
{ "v3.9.0a5", opcode_39 },
{ "v3.9.0a6", opcode_39 },
{ "v3.9.0b1", opcode_39 },
{ "v3.9.0b2", opcode_39 },
{ "v3.9.0b3", opcode_39 },
{ "v3.9.0b4", opcode_39 },
{ "v3.9.0b5", opcode_39 },
{ "v3.9.0rc1", opcode_39 },
{ "v3.9.0rc2", opcode_39 },
{ "v3.9.0", opcode_39 },
{ "v3.9.1", opcode_39 },
{ "v3.9.2", opcode_39 },
{ "v3.9.3", opcode_39 },
{ "v3.9.4", opcode_39 },
{ "v3.9.5", opcode_39 },
{ "v3.9.6", opcode_39 },
{ "v3.9.7", opcode_39 },
{ "v3.9.8", opcode_39 },
{ "v3.9.9", opcode_39 },
{ "v3.9.10", opcode_39 },
{ "v3.9.11", opcode_39 },
{ "v3.9.12", opcode_39 },
{ NULL, NULL },
};
bool pyc_opcodes_equal(pyc_opcodes *op, const char *version) {
if (version == NULL || op == NULL) {
return false;
}
version_opcode *vop = version_op;
while (vop->version) {
if (!strcmp(vop->version, version)) {
if (vop->opcode_func == (pyc_opcodes * (*)())(op->version_sig)) {
return true;
}
}
vop++;
}
return false;
}
pyc_opcodes *get_opcode_by_version(char *version) {
if (version == NULL) {
return NULL;
}
version_opcode *vop = version_op;
while (vop->version) {
if (!strcmp(vop->version, version)) {
return vop->opcode_func();
}
vop++;
}
return NULL; // No match version
}
pyc_opcodes *new_pyc_opcodes() {
size_t i, j;
pyc_opcodes *ret = RZ_NEW0(pyc_opcodes);
if (!ret) {
return NULL;
}
ret->have_argument = 90;
ret->opcodes = malloc(sizeof(pyc_opcode_object) * 256);
if (!ret->opcodes) {
free(ret);
return NULL;
}
for (i = 0; i < 256; i++) {
ret->opcodes[i].op_name = rz_str_newf("<%zu>", i);
if (!ret->opcodes[i].op_name) {
for (j = 0; j < i; j++) {
free(ret->opcodes[j].op_name);
}
free(ret->opcodes);
RZ_FREE(ret);
return NULL;
}
ret->opcodes[i].type = 0;
ret->opcodes[i].op_code = i;
ret->opcodes[i].op_push = 0;
ret->opcodes[i].op_pop = 0;
}
ret->opcode_arg_fmt = rz_list_newf((RzListFree)free);
return ret;
}
void free_opcode(pyc_opcodes *opcodes) {
size_t i;
if (opcodes == NULL || opcodes->opcodes == NULL) {
return;
}
for (i = 0; i < 256; i++) {
if (opcodes->opcodes[i].op_name) {
free(opcodes->opcodes[i].op_name);
}
}
free(opcodes->opcodes);
if (opcodes->opcode_arg_fmt) {
rz_list_free(opcodes->opcode_arg_fmt);
}
free(opcodes);
}
void add_arg_fmt(pyc_opcodes *ret, char *op_name, const char *(*formatter)(ut32 oparg)) {
pyc_arg_fmt *fmt = RZ_NEW0(pyc_arg_fmt);
if (!fmt) {
return;
}
fmt->op_name = op_name;
fmt->formatter = formatter;
rz_list_append(ret->opcode_arg_fmt, fmt);
}
void(def_opN)(struct op_parameter par) {
free(par.op_obj[par.op_code].op_name);
par.op_obj[par.op_code].op_name = strdup(par.op_name);
par.op_obj[par.op_code].op_code = par.op_code;
par.op_obj[par.op_code].op_pop = par.pop;
par.op_obj[par.op_code].op_push = par.push;
if (!par.fallthrough) {
par.op_obj[par.op_code].type |= NOFOLLOW;
}
}
void(name_opN)(struct op_parameter par) {
def_op(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push);
par.op_obj[par.op_code].type |= HASNAME;
}
void(local_opN)(struct op_parameter par) {
def_op(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push);
par.op_obj[par.op_code].type |= HASLOCAL;
}
void(free_opN)(struct op_parameter par) {
def_op(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push);
par.op_obj[par.op_code].type |= HASFREE;
}
void(store_opN)(struct op_parameter par) {
switch (par.func) {
case NAME_OP:
name_op(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push);
break;
case LOCAL_OP:
local_op(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push);
break;
case FREE_OP:
free_op(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push);
break;
case DEF_OP:
def_op(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push);
break;
default:
RZ_LOG_ERROR("Error in store_op in pyc/opcode.c, call function %u.\n", par.func);
return;
}
par.op_obj[par.op_code].type |= HASSTORE;
}
void(varargs_op)(struct op_parameter par) {
def_op(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push);
par.op_obj[par.op_code].type |= HASVARGS;
}
void(const_opN)(struct op_parameter par) {
def_op(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push);
par.op_obj[par.op_code].type |= HASCONST;
}
void(compare_op)(struct op_parameter par) {
def_op(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push);
par.op_obj[par.op_code].type |= HASCOMPARE;
}
void(jabs_opN)(struct op_parameter par) {
def_op00(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push, .fallthrough = par.fallthrough);
par.op_obj[par.op_code].type |= HASJABS;
if (par.conditional) {
par.op_obj[par.op_code].type |= HASCONDITION;
}
}
void(jrel_opN)(struct op_parameter par) {
def_op00(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push, .fallthrough = par.fallthrough);
par.op_obj[par.op_code].type |= HASJREL;
if (par.conditional) {
par.op_obj[par.op_code].type |= HASCONDITION;
}
}
void(nargs_op)(struct op_parameter par) {
def_op(.op_obj = par.op_obj, .op_name = par.op_name, .op_code = par.op_code, .pop = par.pop, .push = par.push);
par.op_obj[par.op_code].type |= HASNARGS;
}
void(rm_op)(struct op_parameter par) {
pyc_opcode_object *op_obj = &par.op_obj[par.op_code];
if (op_obj->op_code == par.op_code && !strcmp(op_obj->op_name, par.op_name)) {
free(op_obj->op_name);
op_obj->op_name = rz_str_newf("<%u>", par.op_code);
op_obj->type = op_obj->op_pop = op_obj->op_push = 0;
} else {
RZ_LOG_ERROR("Error in rm_op() while constructing opcodes for .pyc file: \n .op_code = %u, .op_name = %s", par.op_code, par.op_name);
}
}