// SPDX-FileCopyrightText: 2020 FXTi // 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); } }