336 lines
9.3 KiB
C
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);
|
|
}
|
|
}
|