Skip to content

Commit

Permalink
Add basic opcode (disassembly) support for Python 3.11
Browse files Browse the repository at this point in the history
  • Loading branch information
zrax committed Jan 19, 2023
1 parent a3e5ebd commit 9f1d0f2
Show file tree
Hide file tree
Showing 11 changed files with 558 additions and 362 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ endif()
set(PYTHON_VERSIONS
10 11 13 14 15 16 # Python 1.1 and 1.2 are marshal-identical
20 21 22 23 24 25 26 27
30 31 32 33 34 35 36 37 38 39 310
30 31 32 33 34 35 36 37 38 39 310 311
)

foreach(ver ${PYTHON_VERSIONS})
Expand Down
719 changes: 368 additions & 351 deletions PythonBytecode.txt

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions bytecode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ DECLARE_PYTHON(3, 7)
DECLARE_PYTHON(3, 8)
DECLARE_PYTHON(3, 9)
DECLARE_PYTHON(3, 10)
DECLARE_PYTHON(3, 11)

const char* Pyc::OpcodeName(int opcode)
{
Expand Down Expand Up @@ -103,6 +104,7 @@ int Pyc::ByteToOpcode(int maj, int min, int opcode)
case 8: return python_38_map(opcode);
case 9: return python_39_map(opcode);
case 10: return python_310_map(opcode);
case 11: return python_311_map(opcode);
}
break;
}
Expand Down
30 changes: 30 additions & 0 deletions bytecode_ops.inl
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,15 @@ OPCODE(RERAISE)
OPCODE(WITH_EXCEPT_START)
OPCODE(LOAD_ASSERTION_ERROR)
OPCODE(LIST_TO_TUPLE)
OPCODE(CACHE)
OPCODE(PUSH_NULL)
OPCODE(PUSH_EXC_INFO)
OPCODE(CHECK_EXC_MATCH)
OPCODE(CHECK_EG_MATCH)
OPCODE(BEFORE_WITH)
OPCODE(RETURN_GENERATOR)
OPCODE(ASYNC_GEN_WRAP)
OPCODE(PREP_RERAISE_STAR)

/* Has parameter word */
OPCODE_A_FIRST(STORE_NAME)
Expand Down Expand Up @@ -194,3 +203,24 @@ OPCODE_A(LIST_EXTEND)
OPCODE_A(SET_UPDATE)
OPCODE_A(DICT_MERGE)
OPCODE_A(DICT_UPDATE)
OPCODE_A(SWAP)
OPCODE_A(POP_JUMP_FORWARD_IF_FALSE)
OPCODE_A(POP_JUMP_FORWARD_IF_TRUE)
OPCODE_A(COPY)
OPCODE_A(BINARY_OP)
OPCODE_A(SEND)
OPCODE_A(POP_JUMP_FORWARD_IF_NOT_NONE)
OPCODE_A(POP_JUMP_FORWARD_IF_NONE)
OPCODE_A(GET_AWAITABLE)
OPCODE_A(JUMP_BACKWARD_NO_INTERRUPT)
OPCODE_A(MAKE_CELL)
OPCODE_A(JUMP_BACKWARD)
OPCODE_A(COPY_FREE_VARS)
OPCODE_A(RESUME)
OPCODE_A(PRECALL)
OPCODE_A(CALL)
OPCODE_A(KW_NAMES)
OPCODE_A(POP_JUMP_BACKWARD_IF_NOT_NONE)
OPCODE_A(POP_JUMP_BACKWARD_IF_NONE)
OPCODE_A(POP_JUMP_BACKWARD_IF_FALSE)
OPCODE_A(POP_JUMP_BACKWARD_IF_TRUE)
2 changes: 1 addition & 1 deletion bytes/comp_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

maplist = [ 10, 11, 13, 14, 15, 16,
20, 21, 22, 23, 24, 25, 26, 27,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 310 ]
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 310, 311 ]

for mapver in maplist:
infile = open(os.path.join(sys.argv[1], 'python_%d.map' % mapver), 'rt')
Expand Down
110 changes: 110 additions & 0 deletions bytes/python_311.map
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
0 CACHE
1 POP_TOP
2 PUSH_NULL
9 NOP
10 UNARY_POSITIVE
11 UNARY_NEGATIVE
12 UNARY_NOT
15 UNARY_INVERT
25 BINARY_SUBSCR
30 GET_LEN
31 MATCH_MAPPING
32 MATCH_SEQUENCE
33 MATCH_KEYS
35 PUSH_EXC_INFO
36 CHECK_EXC_MATCH
37 CHECK_EG_MATCH
49 WITH_EXCEPT_START
50 GET_AITER
51 GET_ANEXT
52 BEFORE_ASYNC_WITH
53 BEFORE_WITH
54 END_ASYNC_FOR
60 STORE_SUBSCR
61 DELETE_SUBSCR
68 GET_ITER
69 GET_YIELD_FROM_ITER
70 PRINT_EXPR
71 LOAD_BUILD_CLASS
74 LOAD_ASSERTION_ERROR
75 RETURN_GENERATOR
82 LIST_TO_TUPLE
83 RETURN_VALUE
84 IMPORT_STAR
85 SETUP_ANNOTATIONS
86 YIELD_VALUE
87 ASYNC_GEN_WRAP
88 PREP_RERAISE_STAR
89 POP_EXCEPT
90 STORE_NAME_A
91 DELETE_NAME_A
92 UNPACK_SEQUENCE_A
93 FOR_ITER_A
94 UNPACK_EX_A
95 STORE_ATTR_A
96 DELETE_ATTR_A
97 STORE_GLOBAL_A
98 DELETE_GLOBAL_A
99 SWAP_A
100 LOAD_CONST_A
101 LOAD_NAME_A
102 BUILD_TUPLE_A
103 BUILD_LIST_A
104 BUILD_SET_A
105 BUILD_MAP_A
106 LOAD_ATTR_A
107 COMPARE_OP_A
108 IMPORT_NAME_A
109 IMPORT_FROM_A
110 JUMP_FORWARD_A
111 JUMP_IF_FALSE_OR_POP_A
112 JUMP_IF_TRUE_OR_POP_A
114 POP_JUMP_FORWARD_IF_FALSE_A
115 POP_JUMP_FORWARD_IF_TRUE_A
116 LOAD_GLOBAL_A
117 IS_OP_A
118 CONTAINS_OP_A
119 RERAISE_A
120 COPY_A
122 BINARY_OP_A
123 SEND_A
124 LOAD_FAST_A
125 STORE_FAST_A
126 DELETE_FAST_A
128 POP_JUMP_FORWARD_IF_NOT_NONE_A
129 POP_JUMP_FORWARD_IF_NONE_A
130 RAISE_VARARGS_A
131 GET_AWAITABLE_A
132 MAKE_FUNCTION_A
133 BUILD_SLICE_A
134 JUMP_BACKWARD_NO_INTERRUPT_A
135 MAKE_CELL_A
136 LOAD_CLOSURE_A
137 LOAD_DEREF_A
138 STORE_DEREF_A
139 DELETE_DEREF_A
140 JUMP_BACKWARD_A
142 CALL_FUNCTION_EX_A
144 EXTENDED_ARG_A
145 LIST_APPEND_A
146 SET_ADD_A
147 MAP_ADD_A
148 LOAD_CLASSDEREF_A
149 COPY_FREE_VARS_A
151 RESUME_A
152 MATCH_CLASS_A
155 FORMAT_VALUE_A
156 BUILD_CONST_KEY_MAP_A
157 BUILD_STRING_A
160 LOAD_METHOD_A
162 LIST_EXTEND_A
163 SET_UPDATE_A
164 DICT_MERGE_A
165 DICT_UPDATE_A
166 PRECALL_A
171 CALL_A
172 KW_NAMES_A
173 POP_JUMP_BACKWARD_IF_NOT_NONE_A
174 POP_JUMP_BACKWARD_IF_NONE_A
175 POP_JUMP_BACKWARD_IF_FALSE_A
176 POP_JUMP_BACKWARD_IF_TRUE_A
28 changes: 24 additions & 4 deletions pyc_code.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void PycCode::load(PycData* stream, PycModule* mod)

if (mod->verCompare(1, 3) >= 0 && mod->verCompare(2, 3) < 0)
m_numLocals = stream->get16();
else if (mod->verCompare(2, 3) >= 0)
else if (mod->verCompare(2, 3) >= 0 && mod->verCompare(3, 11) < 0)
m_numLocals = stream->get32();
else
m_numLocals = 0;
Expand All @@ -44,24 +44,39 @@ void PycCode::load(PycData* stream, PycModule* mod)
m_consts = LoadObject(stream, mod).cast<PycSequence>();
m_names = LoadObject(stream, mod).cast<PycSequence>();

if (mod->verCompare(1, 3) >= 0)
if (mod->verCompare(1, 3) >= 0 && mod->verCompare(3, 11) < 0)
m_varNames = LoadObject(stream, mod).cast<PycSequence>();
else
m_varNames = new PycTuple;

if (mod->verCompare(2, 1) >= 0)
if (mod->verCompare(2, 1) >= 0 && mod->verCompare(3, 11) < 0)
m_freeVars = LoadObject(stream, mod).cast<PycSequence>();
else
m_freeVars = new PycTuple;

if (mod->verCompare(2, 1) >= 0)
if (mod->verCompare(2, 1) >= 0 && mod->verCompare(3, 11) < 0)
m_cellVars = LoadObject(stream, mod).cast<PycSequence>();
else
m_cellVars = new PycTuple;

if (mod->verCompare(3, 11) >= 0)
m_localsAndNames = LoadObject(stream, mod).cast<PycSequence>();
else
m_localsAndNames = new PycTuple;

if (mod->verCompare(3, 11) >= 0)
m_localsAndKinds = LoadObject(stream, mod).cast<PycString>();
else
m_localsAndKinds = new PycString;

m_fileName = LoadObject(stream, mod).cast<PycString>();
m_name = LoadObject(stream, mod).cast<PycString>();

if (mod->verCompare(3, 11) >= 0)
m_qualName = LoadObject(stream, mod).cast<PycString>();
else
m_qualName = new PycString;

if (mod->verCompare(1, 5) >= 0 && mod->verCompare(2, 3) < 0)
m_firstLine = stream->get16();
else if (mod->verCompare(2, 3) >= 0)
Expand All @@ -71,4 +86,9 @@ void PycCode::load(PycData* stream, PycModule* mod)
m_lnTable = LoadObject(stream, mod).cast<PycString>();
else
m_lnTable = new PycString;

if (mod->verCompare(3, 11) >= 0)
m_exceptTable = LoadObject(stream, mod).cast<PycString>();
else
m_exceptTable = new PycString;
}
8 changes: 8 additions & 0 deletions pyc_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,14 @@ class PycCode : public PycObject {
PycRef<PycSequence> varNames() const { return m_varNames; }
PycRef<PycSequence> freeVars() const { return m_freeVars; }
PycRef<PycSequence> cellVars() const { return m_cellVars; }
PycRef<PycSequence> localsAndNames() const { return m_localsAndNames; }
PycRef<PycString> localsAndKinds() const { return m_localsAndKinds; }
PycRef<PycString> fileName() const { return m_fileName; }
PycRef<PycString> name() const { return m_name; }
PycRef<PycString> qualName() const { return m_qualName; }
int firstLine() const { return m_firstLine; }
PycRef<PycString> lnTable() const { return m_lnTable; }
PycRef<PycString> exceptTable() const { return m_exceptTable; }

PycRef<PycObject> getConst(int idx) const
{
Expand Down Expand Up @@ -89,10 +93,14 @@ class PycCode : public PycObject {
PycRef<PycSequence> m_varNames;
PycRef<PycSequence> m_freeVars;
PycRef<PycSequence> m_cellVars;
PycRef<PycSequence> m_localsAndNames;
PycRef<PycString> m_localsAndKinds;
PycRef<PycString> m_fileName;
PycRef<PycString> m_name;
PycRef<PycString> m_qualName;
int m_firstLine;
PycRef<PycString> m_lnTable;
PycRef<PycString> m_exceptTable;
globals_t m_globalsUsed; /* Global vars used in this code */
};

Expand Down
6 changes: 6 additions & 0 deletions pyc_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,12 @@ void PycModule::setVersion(unsigned int magic)
m_unicode = true;
break;

case MAGIC_3_11:
m_maj = 3;
m_min = 11;
m_unicode = true;
break;

/* Bad Magic detected */
default:
m_maj = -1;
Expand Down
1 change: 1 addition & 0 deletions pyc_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ enum PycMagic {
MAGIC_3_8 = 0x0A0D0D55,
MAGIC_3_9 = 0x0A0D0D61,
MAGIC_3_10 = 0x0A0D0D6F,
MAGIC_3_11 = 0x0A0D0DA7,

INVALID = 0,
};
Expand Down
12 changes: 7 additions & 5 deletions scripts/pymultic
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ PYVERS = {
'3.3': '3.3.7',
'3.4': '3.4.10',
'3.5': '3.5.10',
'3.6': '3.6.13',
'3.7': '3.7.10',
'3.8': '3.8.9',
'3.9': '3.9.4',
'3.10': '3.10.0',
'3.6': '3.6.15',
'3.7': '3.7.15',
'3.8': '3.8.15',
'3.9': '3.9.15',
'3.10': '3.10.8',
'3.11': '3.11.0',
}

OLD_PYTHONS = ('1.0', '1.1', '1.2', '1.3', '1.4', '1.5')
Expand All @@ -52,6 +53,7 @@ PYVER_CONTAINERS = {
'3.8',
'3.9',
'3.10',
'3.11',
}
CONTAINER_EXES = ['podman', 'docker']
CONTAINER_EXE_EXTRA_ARGS = {
Expand Down

0 comments on commit 9f1d0f2

Please sign in to comment.