mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-28 07:47:02 -05:00
336 lines
8.9 KiB
Rust
336 lines
8.9 KiB
Rust
#pragma description Python bytecode
|
|
|
|
import type.time;
|
|
import std.mem;
|
|
|
|
#define FLAG_REF 0x80
|
|
#define TYPE_NULL '0'
|
|
#define TYPE_NONE 'N'
|
|
#define TYPE_FALSE 'F'
|
|
#define TYPE_TRUE 'T'
|
|
#define TYPE_STOPITER 'S'
|
|
#define TYPE_ELLIPSIS '.'
|
|
#define TYPE_INT 'i'
|
|
#define TYPE_INT64 'I'
|
|
#define TYPE_FLOAT 'f'
|
|
#define TYPE_BINARY_FLOAT 'g'
|
|
#define TYPE_COMPLEX 'x'
|
|
#define TYPE_BINARY_COMPLEX 'y'
|
|
#define TYPE_LONG 'l'
|
|
#define TYPE_STRING 's'
|
|
#define TYPE_INTERNED 't'
|
|
#define TYPE_REF 'r'
|
|
#define TYPE_STRINGREF 'R'
|
|
#define TYPE_TUPLE '('
|
|
#define TYPE_LIST '['
|
|
#define TYPE_DICT '{'
|
|
#define TYPE_CODE 'c'
|
|
#define TYPE_UNICODE 'u'
|
|
#define TYPE_UNKNOWN '?'
|
|
#define TYPE_SET '<'
|
|
#define TYPE_FROZENSET '>'
|
|
#define TYPE_ASCII 'a'
|
|
#define TYPE_ASCII_INTERNED 'A'
|
|
#define TYPE_SMALL_TUPLE ')'
|
|
#define TYPE_SHORT_ASCII 'z'
|
|
#define TYPE_SHORT_ASCII_INTERNED 'Z'
|
|
#define MAX_REFS 2048
|
|
|
|
using MarshalObject;
|
|
u8 _major;
|
|
u8 _minor;
|
|
|
|
fn above(u8 major, u8 minor) {
|
|
return _major >= major && _minor >= minor;
|
|
};
|
|
|
|
fn below(u8 major, u8 minor) {
|
|
return _major <=major && _minor < minor;
|
|
};
|
|
|
|
fn between(u8 major, u8 minor, u8 otherMajor, u8 otherMinor) {
|
|
return above(major, minor) && below(otherMajor, otherMinor);
|
|
};
|
|
|
|
struct NoneObject {};
|
|
|
|
struct MarshalString {
|
|
if(parent.type == TYPE_SHORT_ASCII || parent.type == TYPE_SHORT_ASCII_INTERNED)
|
|
u8 length;
|
|
else
|
|
u32 length;
|
|
|
|
char data[length];
|
|
};
|
|
|
|
struct MarshalSequence {
|
|
if(parent.type == TYPE_SMALL_TUPLE)
|
|
u8 length;
|
|
else
|
|
u32 length;
|
|
MarshalObject values[length];
|
|
};
|
|
|
|
struct MarshalCode {
|
|
if(between(1, 3, 2, 3)) u16 numArgs;
|
|
else if(above(2, 3)) u32 numArgs;
|
|
|
|
if(above(3, 8)) u32 numPosOnlyArgs;
|
|
|
|
if(_major >= 3) u32 numKwOnlyArgs;
|
|
|
|
if(between(1, 3, 2, 3)) u16 numLocals;
|
|
else if(between(2, 3, 3, 11)) u32 numLocals;
|
|
|
|
if(between(1, 5, 2, 3)) u16 numStack;
|
|
else if(above(2, 3)) u32 numStack;
|
|
|
|
if(between(1, 3, 2, 3)) u16 flags;
|
|
else if(above(2, 3)) u32 flags;
|
|
|
|
MarshalObject code;
|
|
MarshalObject constants;
|
|
MarshalObject names;
|
|
|
|
if(above(1, 3)) MarshalObject localNames;
|
|
|
|
if(above(3, 11)) MarshalObject localKinds;
|
|
|
|
if(between(2, 1, 3, 11)) {
|
|
MarshalObject freeVars;
|
|
MarshalObject cellVars;
|
|
}
|
|
|
|
MarshalObject fileName;
|
|
MarshalObject name;
|
|
|
|
if(above(3, 11)) MarshalObject qualifiedName;
|
|
|
|
if(between(1, 5, 2, 3)) u16 firstLine;
|
|
else if(above(2, 3)) u32 firstLine;
|
|
|
|
if(above(1, 5)) MarshalObject lnTable;
|
|
|
|
if(above(3, 11)) MarshalObject exceptionTable;
|
|
};
|
|
|
|
struct DictEntry {
|
|
MarshalObject key;
|
|
if(key.type == TYPE_NULL) break;
|
|
MarshalObject value;
|
|
};
|
|
|
|
struct MarshalDict {
|
|
DictEntry entries[while(true)];
|
|
};
|
|
|
|
struct LongInt {
|
|
u32 len;
|
|
u16 buffer[len];
|
|
};
|
|
|
|
struct LongFloat {
|
|
u8 len;
|
|
u8 buffer[len];
|
|
};
|
|
|
|
struct LongComplex {
|
|
LongFloat real;
|
|
LongFloat imag;
|
|
};
|
|
|
|
auto section = std::mem::create_section("ref-address");
|
|
u128 refs[MAX_REFS] @ 0x0 in section;
|
|
u32 refIndex;
|
|
|
|
fn refMember(u128 address) {
|
|
refs[refIndex] = address;
|
|
refIndex += 1;
|
|
};
|
|
|
|
fn getRef(u32 index) {
|
|
return refs[index];
|
|
};
|
|
|
|
struct MarshalObject {
|
|
u8 _type [[hidden]];
|
|
u8 flag = _type & FLAG_REF;
|
|
u8 type = _type & ~FLAG_REF;
|
|
|
|
if(flag) {
|
|
refMember($-1);
|
|
}
|
|
|
|
match(type) {
|
|
(TYPE_NULL | TYPE_NONE | TYPE_STOPITER | TYPE_ELLIPSIS | TYPE_FALSE | TYPE_TRUE): continue;
|
|
(TYPE_CODE): {
|
|
MarshalCode code [[inline]];
|
|
}
|
|
(TYPE_STRING |
|
|
TYPE_UNICODE |
|
|
TYPE_ASCII |
|
|
TYPE_ASCII_INTERNED |
|
|
TYPE_SHORT_ASCII |
|
|
TYPE_SHORT_ASCII_INTERNED): {
|
|
MarshalString string [[inline]];
|
|
}
|
|
(TYPE_SMALL_TUPLE | TYPE_TUPLE | TYPE_LIST | TYPE_SET | TYPE_FROZENSET): {
|
|
MarshalSequence sequence [[inline]];
|
|
}
|
|
(TYPE_DICT): {
|
|
MarshalDict dict [[inline]];
|
|
}
|
|
(TYPE_INT): {
|
|
u32 int;
|
|
}
|
|
(TYPE_INT64): {
|
|
u64 long;
|
|
}
|
|
(TYPE_FLOAT): {
|
|
LongFloat number;
|
|
}
|
|
(TYPE_BINARY_FLOAT): {
|
|
double number;
|
|
}
|
|
(TYPE_COMPLEX): {
|
|
LongComplex complex;
|
|
}
|
|
(TYPE_BINARY_COMPLEX): {
|
|
double real;
|
|
double imag;
|
|
}
|
|
(TYPE_LONG): {
|
|
LongInt long;
|
|
}
|
|
(TYPE_REF): {
|
|
u32 index;
|
|
MarshalObject obj @ getRef(index);
|
|
}
|
|
(_): {
|
|
std::print("Unknown marshal object type: {:c}", type);
|
|
}
|
|
}
|
|
|
|
} [[format("format_marshal")]];
|
|
|
|
fn format_marshal(ref auto obj) {
|
|
match(obj.type) {
|
|
(TYPE_NONE): return "None";
|
|
(TYPE_STOPITER): return "StopIteration";
|
|
(TYPE_ELLIPSIS): return "...";
|
|
(TYPE_FALSE): return "False";
|
|
(TYPE_TRUE): return "True";
|
|
(TYPE_INT): return "int";
|
|
(TYPE_INT64): return "int64";
|
|
(TYPE_FLOAT): return "float";
|
|
(TYPE_BINARY_FLOAT): return "float";
|
|
(TYPE_COMPLEX): return "complex";
|
|
(TYPE_BINARY_COMPLEX): return "complex";
|
|
(TYPE_LONG): return "long";
|
|
(TYPE_STRING): return "string";
|
|
(TYPE_INTERNED): return "interned";
|
|
(TYPE_REF): return "ref";
|
|
(TYPE_TUPLE): return "tuple";
|
|
(TYPE_LIST): return "list";
|
|
(TYPE_DICT): return "dict";
|
|
(TYPE_CODE): return "code";
|
|
(TYPE_UNICODE): return "unicode";
|
|
(TYPE_UNKNOWN): return "unknown";
|
|
(TYPE_SET): return "set";
|
|
(TYPE_FROZENSET): return "frozenset";
|
|
(TYPE_ASCII): return "ascii";
|
|
(TYPE_ASCII_INTERNED): return "ascii_interned";
|
|
(TYPE_SHORT_ASCII): return "short_ascii";
|
|
(TYPE_SHORT_ASCII_INTERNED): return "short_ascii_interned";
|
|
(TYPE_SMALL_TUPLE): return "small_tuple";
|
|
}
|
|
};
|
|
|
|
enum Magic : u32 {
|
|
MAGIC_1_0 = 0x00999902,
|
|
MAGIC_1_1 = 0x00999903, /* Also covers 1.2 */
|
|
MAGIC_1_3 = 0x0A0D2E89,
|
|
MAGIC_1_4 = 0x0A0D1704,
|
|
MAGIC_1_5 = 0x0A0D4E99,
|
|
MAGIC_1_6 = 0x0A0DC4FC,
|
|
|
|
MAGIC_2_0 = 0x0A0DC687,
|
|
MAGIC_2_1 = 0x0A0DEB2A,
|
|
MAGIC_2_2 = 0x0A0DED2D,
|
|
MAGIC_2_3 = 0x0A0DF23B,
|
|
MAGIC_2_4 = 0x0A0DF26D,
|
|
MAGIC_2_5 = 0x0A0DF2B3,
|
|
MAGIC_2_6 = 0x0A0DF2D1,
|
|
MAGIC_2_7 = 0x0A0DF303,
|
|
|
|
MAGIC_3_0 = 0x0A0D0C3A,
|
|
MAGIC_3_1 = 0x0A0D0C4E,
|
|
MAGIC_3_2 = 0x0A0D0C6C,
|
|
MAGIC_3_3 = 0x0A0D0C9E,
|
|
MAGIC_3_4 = 0x0A0D0CEE,
|
|
MAGIC_3_5 = 0x0A0D0D16,
|
|
MAGIC_3_5_3 = 0x0A0D0D17,
|
|
MAGIC_3_6 = 0x0A0D0D33,
|
|
MAGIC_3_7 = 0x0A0D0D42,
|
|
MAGIC_3_8 = 0x0A0D0D55,
|
|
MAGIC_3_9 = 0x0A0D0D61,
|
|
MAGIC_3_10 = 0x0A0D0D6F,
|
|
MAGIC_3_11 = 0x0A0D0DA7,
|
|
|
|
INVALID = 0,
|
|
};
|
|
|
|
fn getMajor(Magic magic) {
|
|
match(magic) {
|
|
(Magic::MAGIC_1_0 | Magic::MAGIC_1_1 | Magic::MAGIC_1_3 | Magic::MAGIC_1_4 | Magic::MAGIC_1_5 | Magic::MAGIC_1_6): return 1;
|
|
(Magic::MAGIC_2_0 | Magic::MAGIC_2_1 | Magic::MAGIC_2_2 | Magic::MAGIC_2_3 | Magic::MAGIC_2_4 | Magic::MAGIC_2_5 | Magic::MAGIC_2_6 | Magic::MAGIC_2_7): return 2;
|
|
(Magic::MAGIC_3_0 | Magic::MAGIC_3_1 | Magic::MAGIC_3_2 | Magic::MAGIC_3_3 | Magic::MAGIC_3_4 | Magic::MAGIC_3_5 | Magic::MAGIC_3_5_3 | Magic::MAGIC_3_6 | Magic::MAGIC_3_7 | Magic::MAGIC_3_8 | Magic::MAGIC_3_9 | Magic::MAGIC_3_10 | Magic::MAGIC_3_11): return 3;
|
|
(Magic::INVALID): return 0;
|
|
}
|
|
};
|
|
|
|
fn getMinor(Magic magic) {
|
|
match(magic) {
|
|
(Magic::MAGIC_1_0 | Magic::MAGIC_2_0 | Magic::MAGIC_3_0): return 0;
|
|
(Magic::MAGIC_1_1 | Magic::MAGIC_2_1 | Magic::MAGIC_3_1): return 1;
|
|
(Magic::MAGIC_1_3 | Magic::MAGIC_2_2 | Magic::MAGIC_3_2): return 2;
|
|
(Magic::MAGIC_1_4 | Magic::MAGIC_2_3 | Magic::MAGIC_3_3): return 3;
|
|
(Magic::MAGIC_1_5 | Magic::MAGIC_2_4 | Magic::MAGIC_3_4): return 4;
|
|
(Magic::MAGIC_1_6 | Magic::MAGIC_2_5 | Magic::MAGIC_3_5 | Magic::MAGIC_3_5_3): return 5;
|
|
(Magic::MAGIC_2_6 | Magic::MAGIC_3_6): return 6;
|
|
(Magic::MAGIC_2_7 | Magic::MAGIC_3_7): return 7;
|
|
(Magic::MAGIC_3_8): return 8;
|
|
(Magic::MAGIC_3_9): return 9;
|
|
(Magic::MAGIC_3_10): return 10;
|
|
(Magic::MAGIC_3_11): return 11;
|
|
(Magic::INVALID): return 0;
|
|
}
|
|
};
|
|
|
|
struct PYCHeader {
|
|
Magic magic;
|
|
_major = getMajor(magic);
|
|
_minor = getMinor(magic);
|
|
u8 major = _major [[export]];
|
|
u8 minor = _minor [[export]];
|
|
|
|
if(above(3, 7)) {
|
|
u32 flags;
|
|
} else {
|
|
u32 flags;
|
|
}
|
|
|
|
if(flags & 0x1) {
|
|
u64 checksum;
|
|
} else {
|
|
type::time32_t timestamp;
|
|
|
|
if(above(3, 3)) {
|
|
u32 size;
|
|
}
|
|
}
|
|
|
|
MarshalObject object;
|
|
};
|
|
|
|
PYCHeader header @ 0x0; |