Python 3.10 Support (#3577)
* Extract major and minor from python version string instead of converting it to double The patch fixes 3.10 version extraction (3.10 == 3.1) * update latest python magic version to 3491 in get_code_object * opcodes for python3.10 * PYC: do not search for strings in code * PYC python 3.10 tests * Fixed typo in "pyc 3.9 sections" test * pyc: refactored string search * pyc: removed parse_version_major_minor use "magic_int_within" to check python version
This commit is contained in:
parent
5f14d0e0b5
commit
d9a5cf3d28
12 changed files with 295 additions and 86 deletions
|
|
@ -220,6 +220,7 @@ rz_analysis_sources = [
|
|||
'../asm/arch/pyc/opcode_37.c',
|
||||
'../asm/arch/pyc/opcode_38.c',
|
||||
'../asm/arch/pyc/opcode_39.c',
|
||||
'../asm/arch/pyc/opcode_310.c',
|
||||
'../asm/arch/pyc/opcode_3x.c',
|
||||
'../asm/arch/pyc/opcode_analysis.c',
|
||||
'../asm/arch/pyc/opcode_arg_fmt.c',
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include "../../asm/arch/pyc/pyc_dis.h"
|
||||
|
||||
#define JMP_OFFSET(ops, v) ((ops)->jump_use_instruction_offset ? (v)*2 : (v))
|
||||
|
||||
static int archinfo(RzAnalysis *analysis, RzAnalysisInfoType query) {
|
||||
if (!strcmp(analysis->cpu, "x86")) {
|
||||
return -1;
|
||||
|
|
@ -103,7 +105,7 @@ static int pyc_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *data, i
|
|||
|
||||
if (op_obj->type & HASJABS) {
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
|
||||
op->jump = func_base + oparg;
|
||||
op->jump = func_base + JMP_OFFSET(ops, oparg);
|
||||
|
||||
if (op_obj->type & HASCONDITION) {
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
|
||||
|
|
@ -113,7 +115,7 @@ static int pyc_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *data, i
|
|||
}
|
||||
if (op_obj->type & HASJREL) {
|
||||
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
|
||||
op->jump = addr + oparg + ((is_python36) ? 2 : 3);
|
||||
op->jump = addr + ((is_python36) ? 2 : 3) + JMP_OFFSET(ops, oparg);
|
||||
op->fail = addr + ((is_python36) ? 2 : 3);
|
||||
|
||||
if (op_obj->type & HASCONDITION) {
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ static version_opcode version_op[] = {
|
|||
{ "v3.9.10", opcode_39 },
|
||||
{ "v3.9.11", opcode_39 },
|
||||
{ "v3.9.12", opcode_39 },
|
||||
{ "v3.10.0", opcode_310 },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
|
|
@ -188,6 +189,7 @@ pyc_opcodes *new_pyc_opcodes() {
|
|||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
ret->jump_use_instruction_offset = false;
|
||||
ret->have_argument = 90;
|
||||
ret->opcodes = malloc(sizeof(pyc_opcode_object) * 256);
|
||||
if (!ret->opcodes) {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ typedef struct {
|
|||
ut8 extended_arg;
|
||||
ut8 have_argument;
|
||||
ut8 bits;
|
||||
bool jump_use_instruction_offset;
|
||||
void *(*version_sig)();
|
||||
RzList /*<pyc_arg_fmt *>*/ *opcode_arg_fmt;
|
||||
pyc_opcode_object *opcodes;
|
||||
|
|
@ -95,6 +96,7 @@ pyc_opcodes *opcode_36(void);
|
|||
pyc_opcodes *opcode_37(void);
|
||||
pyc_opcodes *opcode_38(void);
|
||||
pyc_opcodes *opcode_39(void);
|
||||
pyc_opcodes *opcode_310(void);
|
||||
|
||||
pyc_opcodes *get_opcode_by_version(char *version);
|
||||
|
||||
|
|
|
|||
16
librz/asm/arch/pyc/opcode_310.c
Normal file
16
librz/asm/arch/pyc/opcode_310.c
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// SPDX-FileCopyrightText: 2023 FXTi <lucaborza@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include "opcode.h"
|
||||
|
||||
pyc_opcodes *opcode_310(void) {
|
||||
pyc_opcodes *ret = opcode_39();
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret->version_sig = (void *(*)())opcode_310;
|
||||
ret->jump_use_instruction_offset = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -207,6 +207,7 @@ rz_asm_sources = [
|
|||
'arch/pyc/opcode_37.c',
|
||||
'arch/pyc/opcode_38.c',
|
||||
'arch/pyc/opcode_39.c',
|
||||
'arch/pyc/opcode_310.c',
|
||||
'arch/pyc/opcode_3x.c',
|
||||
'arch/pyc/opcode_analysis.c',
|
||||
'arch/pyc/opcode_arg_fmt.c',
|
||||
|
|
|
|||
|
|
@ -424,7 +424,28 @@ static pyc_object *get_string_object(RzBuffer *buffer) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static pyc_object *get_unicode_object(RzBuffer *buffer) {
|
||||
static bool add_string_to_cache(RzBinPycObj *pyc, ut64 addr, const char *data, ut32 size, ut32 length, RzStrEnc type) {
|
||||
if (size == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RzBinString *string = RZ_NEW0(RzBinString);
|
||||
if (!string) {
|
||||
return false;
|
||||
}
|
||||
string->paddr = string->vaddr = addr;
|
||||
string->size = size;
|
||||
string->length = length;
|
||||
string->ordinal = 0;
|
||||
string->type = type;
|
||||
string->string = rz_str_new(data);
|
||||
if (!rz_list_append(pyc->strings_cache, string)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static pyc_object *get_unicode_object(RzBinPycObj *pyc, RzBuffer *buffer) {
|
||||
pyc_object *ret = NULL;
|
||||
bool error = false;
|
||||
ut32 n = 0;
|
||||
|
|
@ -437,6 +458,7 @@ static pyc_object *get_unicode_object(RzBuffer *buffer) {
|
|||
if (error) {
|
||||
return NULL;
|
||||
}
|
||||
ut64 addr = rz_buf_tell(buffer);
|
||||
ret = RZ_NEW0(pyc_object);
|
||||
ret->type = TYPE_UNICODE;
|
||||
ret->data = get_bytes(buffer, n);
|
||||
|
|
@ -444,6 +466,11 @@ static pyc_object *get_unicode_object(RzBuffer *buffer) {
|
|||
RZ_FREE(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!add_string_to_cache(pyc, addr, ret->data, n, rz_utf8_strlen(ret->data), RZ_STRING_ENC_UTF8)) {
|
||||
RZ_FREE(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -627,22 +654,29 @@ static pyc_object *get_set_object(RzBinPycObj *pyc, RzBuffer *buffer) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static pyc_object *get_ascii_object_generic(RzBuffer *buffer, ut32 size, bool interned) {
|
||||
static pyc_object *get_ascii_object_generic(RzBinPycObj *pyc, RzBuffer *buffer, ut32 size, bool interned) {
|
||||
pyc_object *ret = NULL;
|
||||
|
||||
ret = RZ_NEW0(pyc_object);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ut64 addr = rz_buf_tell(buffer);
|
||||
ret->type = TYPE_ASCII;
|
||||
ret->data = get_bytes(buffer, size);
|
||||
if (!ret->data) {
|
||||
RZ_FREE(ret);
|
||||
}
|
||||
|
||||
if (!add_string_to_cache(pyc, addr, ret->data, size, size, RZ_STRING_ENC_8BIT)) {
|
||||
RZ_FREE(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static pyc_object *get_ascii_object(RzBuffer *buffer) {
|
||||
static pyc_object *get_ascii_object(RzBinPycObj *pyc, RzBuffer *buffer) {
|
||||
bool error = false;
|
||||
ut32 n = 0;
|
||||
|
||||
|
|
@ -650,10 +684,10 @@ static pyc_object *get_ascii_object(RzBuffer *buffer) {
|
|||
if (error) {
|
||||
return NULL;
|
||||
}
|
||||
return get_ascii_object_generic(buffer, n, true);
|
||||
return get_ascii_object_generic(pyc, buffer, n, true);
|
||||
}
|
||||
|
||||
static pyc_object *get_ascii_interned_object(RzBuffer *buffer) {
|
||||
static pyc_object *get_ascii_interned_object(RzBinPycObj *pyc, RzBuffer *buffer) {
|
||||
bool error = false;
|
||||
ut32 n;
|
||||
|
||||
|
|
@ -661,10 +695,10 @@ static pyc_object *get_ascii_interned_object(RzBuffer *buffer) {
|
|||
if (error) {
|
||||
return NULL;
|
||||
}
|
||||
return get_ascii_object_generic(buffer, n, true);
|
||||
return get_ascii_object_generic(pyc, buffer, n, true);
|
||||
}
|
||||
|
||||
static pyc_object *get_short_ascii_object(RzBuffer *buffer) {
|
||||
static pyc_object *get_short_ascii_object(RzBinPycObj *pyc, RzBuffer *buffer) {
|
||||
bool error = false;
|
||||
ut8 n;
|
||||
|
||||
|
|
@ -672,10 +706,10 @@ static pyc_object *get_short_ascii_object(RzBuffer *buffer) {
|
|||
if (error) {
|
||||
return NULL;
|
||||
}
|
||||
return get_ascii_object_generic(buffer, n, false);
|
||||
return get_ascii_object_generic(pyc, buffer, n, false);
|
||||
}
|
||||
|
||||
static pyc_object *get_short_ascii_interned_object(RzBuffer *buffer) {
|
||||
static pyc_object *get_short_ascii_interned_object(RzBinPycObj *pyc, RzBuffer *buffer) {
|
||||
bool error = false;
|
||||
ut8 n;
|
||||
|
||||
|
|
@ -683,7 +717,7 @@ static pyc_object *get_short_ascii_interned_object(RzBuffer *buffer) {
|
|||
if (error) {
|
||||
return NULL;
|
||||
}
|
||||
return get_ascii_object_generic(buffer, n, true);
|
||||
return get_ascii_object_generic(pyc, buffer, n, true);
|
||||
}
|
||||
|
||||
static pyc_object *get_ref_object(RzBinPycObj *pyc, RzBuffer *buffer) {
|
||||
|
|
@ -866,7 +900,7 @@ static pyc_object *get_code_object(RzBinPycObj *pyc, RzBuffer *buffer) {
|
|||
bool v15_to_22 = magic_int_within(pyc->magic_int, 20121, 60718, &error); // 1.5a1 - 2.2a1
|
||||
bool v13_to_20 = magic_int_within(pyc->magic_int, 11913, 50824, &error); // 1.3b1 - 2.0b1
|
||||
// bool v21_to_27 = (!v13_to_20) && magic_int_within (magic_int, 60124, 62212, &error);
|
||||
bool has_posonlyargcount = magic_int_within(pyc->magic_int, 3410, 3424, &error); // v3.8.0a4 - latest
|
||||
bool has_posonlyargcount = magic_int_within(pyc->magic_int, 3410, 3491, &error); // v3.8.0a4 - latest
|
||||
if (error) {
|
||||
free(ret);
|
||||
free(cobj);
|
||||
|
|
@ -1051,16 +1085,16 @@ static pyc_object *get_object(RzBinPycObj *pyc, RzBuffer *buffer) {
|
|||
ret = get_int_object(buffer);
|
||||
break;
|
||||
case TYPE_ASCII_INTERNED:
|
||||
ret = get_ascii_interned_object(buffer);
|
||||
ret = get_ascii_interned_object(pyc, buffer);
|
||||
break;
|
||||
case TYPE_SHORT_ASCII:
|
||||
ret = get_short_ascii_object(buffer);
|
||||
ret = get_short_ascii_object(pyc, buffer);
|
||||
break;
|
||||
case TYPE_ASCII:
|
||||
ret = get_ascii_object(buffer);
|
||||
ret = get_ascii_object(pyc, buffer);
|
||||
break;
|
||||
case TYPE_SHORT_ASCII_INTERNED:
|
||||
ret = get_short_ascii_interned_object(buffer);
|
||||
ret = get_short_ascii_interned_object(pyc, buffer);
|
||||
break;
|
||||
case TYPE_INT64:
|
||||
ret = get_int64_object(buffer);
|
||||
|
|
@ -1090,7 +1124,7 @@ static pyc_object *get_object(RzBinPycObj *pyc, RzBuffer *buffer) {
|
|||
ret = get_long_object(buffer);
|
||||
break;
|
||||
case TYPE_UNICODE:
|
||||
ret = get_unicode_object(buffer);
|
||||
ret = get_unicode_object(pyc, buffer);
|
||||
break;
|
||||
case TYPE_DICT:
|
||||
ret = get_dict_object(pyc, buffer);
|
||||
|
|
@ -1151,6 +1185,7 @@ static bool extract_sections_symbols(RzBinPycObj *pyc, pyc_object *obj, RzList /
|
|||
if (!section->name) {
|
||||
goto fail;
|
||||
}
|
||||
section->has_strings = false;
|
||||
section->paddr = cobj->start_offset;
|
||||
section->vaddr = cobj->start_offset;
|
||||
section->size = cobj->end_offset - cobj->start_offset;
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ typedef struct pyc_context {
|
|||
/* used from marshall.c */
|
||||
RzList /*<char *>*/ *interned_table;
|
||||
RzList /*<RzBinSection *>*/ *sections_cache;
|
||||
RzList /*<RzBinString *>*/ *strings_cache;
|
||||
RzList /*<RzBinSymbol *>*/ *symbols_cache;
|
||||
RzList /*<RzList<void *> *>*/ *shared;
|
||||
RzList /*<pyc_object *>*/ *refs; // If you don't have a good reason, do not change this. And also checkout !refs in get_code_object()
|
||||
ut32 magic_int;
|
||||
|
|
|
|||
|
|
@ -312,20 +312,3 @@ bool magic_int_within(ut32 target_magic, ut32 lower, ut32 upper, bool *error) {
|
|||
|
||||
return (li <= ti) && (ti <= ui);
|
||||
}
|
||||
|
||||
double version2double(const char *version) {
|
||||
unsigned idx = 0, buf_idx = 0;
|
||||
char buf[20];
|
||||
double result;
|
||||
|
||||
while (!('0' <= version[idx] && version[idx] <= '9'))
|
||||
idx++;
|
||||
for (; version[idx] != '.'; idx++)
|
||||
buf[buf_idx++] = version[idx];
|
||||
buf[buf_idx++] = version[idx++];
|
||||
for (; '0' <= version[idx] && version[idx] <= '9'; idx++)
|
||||
buf[buf_idx++] = version[idx];
|
||||
buf[buf_idx] = '\x00';
|
||||
sscanf(buf, "%lf", &result);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ struct pyc_version {
|
|||
|
||||
struct pyc_version get_pyc_version(ut32 magic);
|
||||
|
||||
double version2double(const char *version);
|
||||
|
||||
bool magic_int_within(ut32 target_magic, ut32 lower, ut32 uppper, bool *error);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -15,6 +15,50 @@ static bool check_buffer(RzBuffer *b) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool init_pyc_cache(RzBinPycObj *pyc, RzBuffer *buf) {
|
||||
RzList *shared = rz_list_newf((RzListFree)rz_list_free);
|
||||
if (!shared) {
|
||||
return false;
|
||||
}
|
||||
RzList *cobjs = rz_list_newf((RzListFree)free);
|
||||
if (!cobjs) {
|
||||
rz_list_free(shared);
|
||||
return false;
|
||||
}
|
||||
pyc->interned_table = rz_list_newf((RzListFree)free);
|
||||
if (!pyc->interned_table) {
|
||||
rz_list_free(shared);
|
||||
rz_list_free(cobjs);
|
||||
return false;
|
||||
}
|
||||
rz_list_append(shared, cobjs);
|
||||
rz_list_append(shared, pyc->interned_table);
|
||||
pyc->shared = shared;
|
||||
RzList *sections = rz_list_newf((RzListFree)free);
|
||||
if (!sections) {
|
||||
rz_list_free(shared);
|
||||
return false;
|
||||
}
|
||||
pyc->sections_cache = sections;
|
||||
RzList *symbols = rz_list_newf((RzListFree)free);
|
||||
if (!symbols) {
|
||||
rz_list_free(shared);
|
||||
rz_list_free(sections);
|
||||
return false;
|
||||
}
|
||||
pyc->symbols_cache = symbols;
|
||||
RzList *strings = rz_list_newf((RzListFree)free);
|
||||
if (!strings) {
|
||||
rz_list_free(shared);
|
||||
return false;
|
||||
}
|
||||
pyc->strings_cache = strings;
|
||||
|
||||
rz_buf_seek(buf, pyc->code_start_offset, RZ_BUF_SET);
|
||||
pyc_get_sections_symbols(pyc, sections, symbols, cobjs, buf, pyc->version.magic);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb) {
|
||||
RzBinPycObj *ctx = RZ_NEW0(RzBinPycObj);
|
||||
if (!ctx) {
|
||||
|
|
@ -53,6 +97,13 @@ static RzBinInfo *info(RzBinFile *arch) {
|
|||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool error;
|
||||
bool is_before_py_36 = magic_int_within(ctx->version.magic, 0x9494, 0x0d16, &error);
|
||||
if (error) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret->file = strdup(arch->file);
|
||||
ret->type = rz_str_newf("Python %s byte-compiled file", ctx->version.version);
|
||||
ret->bclass = strdup("Python byte-compiled file");
|
||||
|
|
@ -61,17 +112,14 @@ static RzBinInfo *info(RzBinFile *arch) {
|
|||
ret->machine = rz_str_newf("Python %s VM (rev %s)", ctx->version.version,
|
||||
ctx->version.revision);
|
||||
ret->os = strdup("any");
|
||||
ret->bits = version2double(ctx->version.version) < 3.6 ? 16 : 8;
|
||||
ret->bits = is_before_py_36 ? 16 : 8;
|
||||
ret->cpu = strdup(ctx->version.version); // pass version info in cpu, Asm plugin will get it
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RzList /*<RzBinSection *>*/ *sections(RzBinFile *arch) {
|
||||
RzBinPycObj *ctx = arch->o->bin_obj;
|
||||
return ctx->sections_cache;
|
||||
}
|
||||
|
||||
static RzList /*<RzBinAddr *>*/ *entries(RzBinFile *arch) {
|
||||
RzBinPycObj *pyc = arch->o->bin_obj;
|
||||
|
||||
RzList *entries = rz_list_newf((RzListFree)free);
|
||||
if (!entries) {
|
||||
return NULL;
|
||||
|
|
@ -86,6 +134,11 @@ static RzList /*<RzBinAddr *>*/ *entries(RzBinFile *arch) {
|
|||
addr->vaddr = entrypoint;
|
||||
rz_buf_seek(arch->buf, entrypoint, RZ_IO_SEEK_SET);
|
||||
rz_list_append(entries, addr);
|
||||
|
||||
if (!init_pyc_cache(pyc, arch->buf)) {
|
||||
rz_list_free(entries);
|
||||
return NULL;
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
|
|
@ -93,42 +146,19 @@ static ut64 baddr(RzBinFile *bf) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static RzList /*<RzBinSection *>*/ *sections(RzBinFile *arch) {
|
||||
RzBinPycObj *ctx = arch->o->bin_obj;
|
||||
return ctx->sections_cache;
|
||||
}
|
||||
|
||||
static RzList /*<RzBinSymbol *>*/ *symbols(RzBinFile *arch) {
|
||||
RzBinPycObj *pyc = arch->o->bin_obj;
|
||||
RzList *shared = rz_list_newf((RzListFree)rz_list_free);
|
||||
if (!shared) {
|
||||
return NULL;
|
||||
}
|
||||
RzList *cobjs = rz_list_newf((RzListFree)free);
|
||||
if (!cobjs) {
|
||||
rz_list_free(shared);
|
||||
return NULL;
|
||||
}
|
||||
pyc->interned_table = rz_list_newf((RzListFree)free);
|
||||
if (!pyc->interned_table) {
|
||||
rz_list_free(shared);
|
||||
rz_list_free(cobjs);
|
||||
return NULL;
|
||||
}
|
||||
rz_list_append(shared, cobjs);
|
||||
rz_list_append(shared, pyc->interned_table);
|
||||
pyc->shared = shared;
|
||||
RzList *sections = rz_list_newf((RzListFree)free);
|
||||
if (!sections) {
|
||||
rz_list_free(shared);
|
||||
return NULL;
|
||||
}
|
||||
RzList *symbols = rz_list_newf((RzListFree)free);
|
||||
if (!symbols) {
|
||||
rz_list_free(shared);
|
||||
rz_list_free(sections);
|
||||
return NULL;
|
||||
}
|
||||
RzBuffer *buffer = arch->buf;
|
||||
rz_buf_seek(buffer, pyc->code_start_offset, RZ_BUF_SET);
|
||||
pyc_get_sections_symbols(pyc, sections, symbols, cobjs, buffer, pyc->version.magic);
|
||||
pyc->sections_cache = sections;
|
||||
return symbols;
|
||||
return pyc->symbols_cache;
|
||||
}
|
||||
|
||||
static RzList /*<RzBinString *>*/ *strings(RzBinFile *bf) {
|
||||
RzBinPycObj *pyc = bf->o->bin_obj;
|
||||
return pyc->strings_cache;
|
||||
}
|
||||
|
||||
static void destroy(RzBinFile *bf) {
|
||||
|
|
@ -148,6 +178,7 @@ RzBinPlugin rz_bin_plugin_pyc = {
|
|||
.sections = §ions,
|
||||
.baddr = &baddr,
|
||||
.symbols = &symbols,
|
||||
.strings = &strings,
|
||||
.destroy = &destroy
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,19 @@
|
|||
NAME=pyc load version310
|
||||
FILE=bins/pyc/py310.pyc
|
||||
CMDS=<<EOF
|
||||
iI~machine
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
machine Python v3.10.0 VM (rev bfb376ffcc4260feb9bf1b9a110559b1ff31da80)
|
||||
EOF
|
||||
REGEXP_FILTER_ERR=<<EOF
|
||||
free_object\ \(0\)
|
||||
EOF
|
||||
EXPECT_ERR=<<EOF
|
||||
free_object (0)
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=pyc load version39
|
||||
FILE=bins/pyc/py39.pyc
|
||||
CMDS=<<EOF
|
||||
|
|
@ -94,19 +110,41 @@ free_object (0)
|
|||
EOF
|
||||
RUN
|
||||
|
||||
NAME=pyc 3.9 sections
|
||||
FILE=bins/pyc/py37.pyc
|
||||
NAME=pyc 3.10 sections
|
||||
FILE=bins/pyc/py310.pyc
|
||||
CMDS=<<EOF
|
||||
iS~Bat
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x00001f0d 0x2a 0x00001f0d 0x2a 0x0 ---- module_.Bat
|
||||
0x00001f5f 0xa 0x00001f5f 0xa 0x0 ---- module_.Bat.__init
|
||||
0x00001fca 0x8 0x00001fca 0x8 0x0 ---- module_.Bat.say
|
||||
0x00002037 0x4 0x00002037 0x4 0x0 ---- module_.Bat.sonar
|
||||
0x00002103 0x1c 0x00002103 0x1c 0x0 ---- module_.Batman
|
||||
0x00002143 0x44 0x00002143 0x44 0x0 ---- module_.Batman.__init
|
||||
0x00002235 0x4 0x00002235 0x4 0x0 ---- module_.Batman.sing
|
||||
0x0000201d 0x2a 0x0000201d 0x2a 0x0 ---- module_.Bat
|
||||
0x00002073 0x0 0x00002073 0x0 0x0 ---- module_.Bat.__init
|
||||
0x000020da 0x8 0x000020da 0x8 0x0 ---- module_.Bat.say
|
||||
0x00002144 0x0 0x00002144 0x0 0x0 ---- module_.Bat.sonar
|
||||
0x0000220e 0x1c 0x0000220e 0x1c 0x0 ---- module_.Batman
|
||||
0x00002252 0x48 0x00002252 0x48 0x0 ---- module_.Batman.__init
|
||||
0x00002356 0x0 0x00002356 0x0 0x0 ---- module_.Batman.sing
|
||||
EOF
|
||||
REGEXP_FILTER_ERR=<<EOF
|
||||
free_object\ \(0\)
|
||||
EOF
|
||||
EXPECT_ERR=<<EOF
|
||||
free_object (0)
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=pyc 3.9 sections
|
||||
FILE=bins/pyc/py39.pyc
|
||||
CMDS=<<EOF
|
||||
iS~Bat
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x00001fdf 0x2a 0x00001fdf 0x2a 0x0 ---- module_.Bat
|
||||
0x00002035 0xa 0x00002035 0xa 0x0 ---- module_.Bat.__init
|
||||
0x000020a6 0x8 0x000020a6 0x8 0x0 ---- module_.Bat.say
|
||||
0x00002110 0x4 0x00002110 0x4 0x0 ---- module_.Bat.sonar
|
||||
0x000021de 0x1c 0x000021de 0x1c 0x0 ---- module_.Batman
|
||||
0x00002222 0x48 0x00002222 0x48 0x0 ---- module_.Batman.__init
|
||||
0x00002326 0x4 0x00002326 0x4 0x0 ---- module_.Batman.sing
|
||||
EOF
|
||||
REGEXP_FILTER_ERR=<<EOF
|
||||
free_object\ \(0\)
|
||||
|
|
@ -164,6 +202,70 @@ free_object (0)
|
|||
EOF
|
||||
RUN
|
||||
|
||||
NAME=pyc 3.10 disasm
|
||||
FILE=bins/pyc/py310.pyc
|
||||
CMDS=<<EOF
|
||||
pd 10
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
;-- entry0:
|
||||
;-- section.module:
|
||||
;-- <module>:
|
||||
0x0000002e LOAD_CONST Multiline strings can be written
|
||||
using three "s, and are often used
|
||||
as documentation. ; [00] ---- section size 3292 named module
|
||||
0x00000030 STORE_NAME __doc__
|
||||
0x00000032 NOP
|
||||
0x00000034 NOP
|
||||
0x00000036 NOP
|
||||
0x00000038 NOP
|
||||
0x0000003a NOP
|
||||
0x0000003c NOP
|
||||
0x0000003e NOP
|
||||
0x00000040 NOP
|
||||
EOF
|
||||
REGEXP_FILTER_ERR=<<EOF
|
||||
free_object\ \(0\)
|
||||
EOF
|
||||
EXPECT_ERR=<<EOF
|
||||
free_object (0)
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=pyc 3.10 disasm
|
||||
FILE=bins/pyc/py310.pyc
|
||||
CMDS=<<EOF
|
||||
s 0x00001eb3
|
||||
pd 16
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
;-- section.module_.Superhero.boast:
|
||||
;-- <module>.Superhero.boast:
|
||||
0x00001eb3 LOAD_FAST self ; [29] ---- section size 32 named module_.Superhero.boast
|
||||
0x00001eb5 LOAD_ATTR superpowers
|
||||
0x00001eb7 GET_ITER
|
||||
,,.-> 0x00001eb9 FOR_ITER 10
|
||||
`---> 0x00001ebb STORE_FAST power
|
||||
|: 0x00001ebd LOAD_GLOBAL print
|
||||
|: 0x00001ebf LOAD_CONST I wield the power of {pow}!
|
||||
|: 0x00001ec1 LOAD_ATTR format
|
||||
|: 0x00001ec3 LOAD_FAST power
|
||||
|: 0x00001ec5 LOAD_CONST (pow)
|
||||
|: 0x00001ec7 CALL_FUNCTION_KW 1 total positional and keyword args
|
||||
|: 0x00001ec9 CALL_FUNCTION 1
|
||||
|: 0x00001ecb POP_TOP
|
||||
|`=< 0x00001ecd JUMP_ABSOLUTE 3
|
||||
`--> 0x00001ecf LOAD_CONST None
|
||||
0x00001ed1 RETURN_VALUE
|
||||
EOF
|
||||
REGEXP_FILTER_ERR=<<EOF
|
||||
free_object\ \(0\)
|
||||
EOF
|
||||
EXPECT_ERR=<<EOF
|
||||
free_object (0)
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=pyc 3.9 disasm
|
||||
FILE=bins/pyc/py39.pyc
|
||||
CMDS=<<EOF
|
||||
|
|
@ -194,6 +296,40 @@ free_object (0)
|
|||
EOF
|
||||
RUN
|
||||
|
||||
NAME=pyc 3.9 disasm
|
||||
FILE=bins/pyc/py39.pyc
|
||||
CMDS=<<EOF
|
||||
s 0x00001e79
|
||||
pd 16
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
;-- section.module_.Superhero.boast:
|
||||
;-- <module>.Superhero.boast:
|
||||
0x00001e79 LOAD_FAST self ; [29] ---- section size 32 named module_.Superhero.boast
|
||||
0x00001e7b LOAD_ATTR superpowers
|
||||
0x00001e7d GET_ITER
|
||||
,,.-> 0x00001e7f FOR_ITER 20
|
||||
`---> 0x00001e81 STORE_FAST power
|
||||
|: 0x00001e83 LOAD_GLOBAL print
|
||||
|: 0x00001e85 LOAD_CONST I wield the power of {pow}!
|
||||
|: 0x00001e87 LOAD_ATTR format
|
||||
|: 0x00001e89 LOAD_FAST power
|
||||
|: 0x00001e8b LOAD_CONST (pow)
|
||||
|: 0x00001e8d CALL_FUNCTION_KW 1 total positional and keyword args
|
||||
|: 0x00001e8f CALL_FUNCTION 1
|
||||
|: 0x00001e91 POP_TOP
|
||||
|`=< 0x00001e93 JUMP_ABSOLUTE 6
|
||||
`--> 0x00001e95 LOAD_CONST None
|
||||
0x00001e97 RETURN_VALUE
|
||||
EOF
|
||||
REGEXP_FILTER_ERR=<<EOF
|
||||
free_object\ \(0\)
|
||||
EOF
|
||||
EXPECT_ERR=<<EOF
|
||||
free_object (0)
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=pyc 3.7 disasm
|
||||
FILE=bins/pyc/py37.pyc
|
||||
CMDS=<<EOF
|
||||
|
|
|
|||
Loading…
Reference in a new issue