Rizin
unix-like reverse engineering framework and cli tools
opcode_3x.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2020 FXTi <zjxiang1998@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "opcode.h"
5 
8  if (!ret) {
9  return NULL;
10  }
11 
12  ret->version_sig = (void *(*)())opcode_3x;
13 
14  def_op00(.op_obj = ret->opcodes, .op_name = "STOP_CODE", .op_code = 0, .pop = 0, .push = 0, .fallthrough = false);
15  def_op(.op_obj = ret->opcodes, .op_name = "POP_TOP", .op_code = 1, .pop = 1, .push = 0);
16  def_op(.op_obj = ret->opcodes, .op_name = "ROT_TWO", .op_code = 2, .pop = 2, .push = 2);
17  def_op(.op_obj = ret->opcodes, .op_name = "ROT_THREE", .op_code = 3, .pop = 3, .push = 3);
18  def_op(.op_obj = ret->opcodes, .op_name = "DUP_TOP", .op_code = 4, .pop = 0, .push = 1);
19 
20  // Python 3.2+
21  def_op(.op_obj = ret->opcodes, .op_name = "DUP_TOP_TWO", .op_code = 5, .pop = 0, .push = 2);
22 
23  def_op(.op_obj = ret->opcodes, .op_name = "NOP", 9);
24  def_op(.op_obj = ret->opcodes, .op_name = "UNARY_POSITIVE", .op_code = 10, .pop = 1, .push = 1);
25  def_op(.op_obj = ret->opcodes, .op_name = "UNARY_NEGATIVE", .op_code = 11, .pop = 1, .push = 1);
26  def_op(.op_obj = ret->opcodes, .op_name = "UNARY_NOT", .op_code = 12, .pop = 1, .push = 1);
27 
28  def_op(.op_obj = ret->opcodes, .op_name = "UNARY_INVERT", .op_code = 15, .pop = 1, .push = 1);
29 
30  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_POWER", .op_code = 19, .pop = 2, .push = 1);
31  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_MULTIPLY", .op_code = 20, .pop = 2, .push = 1);
32 
33  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_MODULO", .op_code = 22, .pop = 2, .push = 1);
34  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_ADD", .op_code = 23, .pop = 2, .push = 1);
35  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_SUBTRACT", .op_code = 24, .pop = 2, .push = 1);
36  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_SUBSCR", .op_code = 25, .pop = 2, .push = 1);
37  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_FLOOR_DIVIDE", .op_code = 26, .pop = 2, .push = 1);
38  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_TRUE_DIVIDE", .op_code = 27, .pop = 2, .push = 1);
39  def_op(.op_obj = ret->opcodes, .op_name = "INPLACE_FLOOR_DIVIDE", .op_code = 28, .pop = 2, .push = 1);
40  def_op(.op_obj = ret->opcodes, .op_name = "INPLACE_TRUE_DIVIDE", .op_code = 29, .pop = 2, .push = 1);
41 
42  // Gone from Python 3 are Python2's
43  // SLICE+0 .. SLICE+3
44  // STORE_SLICE+0 .. STORE_SLICE+3
45  // DELETE_SLICE+0 .. DELETE_SLICE+3
46 
47  store_op(.op_obj = ret->opcodes, .op_name = "STORE_MAP", .op_code = 54, .pop = 3, .push = 1);
48  def_op(.op_obj = ret->opcodes, .op_name = "INPLACE_ADD", .op_code = 55, .pop = 2, .push = 1);
49  def_op(.op_obj = ret->opcodes, .op_name = "INPLACE_SUBTRACT", .op_code = 56, .pop = 2, .push = 1);
50  def_op(.op_obj = ret->opcodes, .op_name = "INPLACE_MULTIPLY", .op_code = 57, .pop = 2, .push = 1);
51 
52  def_op(.op_obj = ret->opcodes, .op_name = "INPLACE_MODULO", .op_code = 59, .pop = 2, .push = 1);
53  store_op(.op_obj = ret->opcodes, .op_name = "STORE_SUBSCR", .op_code = 60, .pop = 3, .push = 0); // Implements TOS1[TOS] = TOS2.
54  def_op(.op_obj = ret->opcodes, .op_name = "DELETE_SUBSCR", .op_code = 61, .pop = 2, .push = 0); // Implements del TOS1[TOS].
55  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_LSHIFT", .op_code = 62, .pop = 2, .push = 1);
56  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_RSHIFT", .op_code = 63, .pop = 2, .push = 1);
57  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_AND", .op_code = 64, .pop = 2, .push = 1);
58  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_XOR", .op_code = 65, .pop = 2, .push = 1);
59  def_op(.op_obj = ret->opcodes, .op_name = "BINARY_OR", .op_code = 66, .pop = 2, .push = 1);
60  def_op(.op_obj = ret->opcodes, .op_name = "INPLACE_POWER", .op_code = 67, .pop = 2, .push = 1);
61  def_op(.op_obj = ret->opcodes, .op_name = "GET_ITER", .op_code = 68, .pop = 1, .push = 1);
62  store_op(.op_obj = ret->opcodes, .op_name = "STORE_LOCALS", .op_code = 69, .pop = 1, .push = 0);
63 
64  def_op(.op_obj = ret->opcodes, .op_name = "PRINT_EXPR", .op_code = 70, .pop = 1, .push = 0);
65  def_op(.op_obj = ret->opcodes, .op_name = "LOAD_BUILD_CLASS", .op_code = 71, .pop = 0, .push = 1);
66 
67  // Python3 drops/changes:
68  // def_op(.op_obj = ret->opcodes, .op_name = "PRINT_ITEM", 71)
69  // def_op(.op_obj = ret->opcodes, .op_name = "PRINT_NEWLINE", 72)
70  // def_op(.op_obj = ret->opcodes, .op_name = "PRINT_ITEM_TO", 73)
71  // def_op(.op_obj = ret->opcodes, .op_name = "PRINT_NEWLINE_TO", 74)
72 
73  def_op(.op_obj = ret->opcodes, .op_name = "INPLACE_LSHIFT", .op_code = 75, .pop = 2, .push = 1);
74  def_op(.op_obj = ret->opcodes, .op_name = "INPLACE_RSHIFT", .op_code = 76, .pop = 2, .push = 1);
75  def_op(.op_obj = ret->opcodes, .op_name = "INPLACE_AND", .op_code = 77, .pop = 2, .push = 1);
76  def_op(.op_obj = ret->opcodes, .op_name = "INPLACE_XOR", .op_code = 78, .pop = 2, .push = 1);
77  def_op(.op_obj = ret->opcodes, .op_name = "INPLACE_OR", .op_code = 79, .pop = 2, .push = 1);
78  def_op(.op_obj = ret->opcodes, .op_name = "BREAK_LOOP", .op_code = 80, .pop = 0, .push = 0);
79  def_op(.op_obj = ret->opcodes, .op_name = "WITH_CLEANUP", .op_code = 81, .pop = 1, .push = 0); // Cleans up the stack when a with statement
80  // block exits. Handle stack special
81 
82  def_op00(.op_obj = ret->opcodes, .op_name = "RETURN_VALUE", .op_code = 83, .pop = 1, .push = 0, .fallthrough = false);
83  def_op(.op_obj = ret->opcodes, .op_name = "IMPORT_STAR", .op_code = 84, .pop = 1, .push = 0);
84 
85  def_op(.op_obj = ret->opcodes, .op_name = "YIELD_VALUE", .op_code = 86, .pop = 1, .push = 1);
86  def_op(.op_obj = ret->opcodes, .op_name = "POP_BLOCK", .op_code = 87, .pop = 0, .push = 0);
87  def_op(.op_obj = ret->opcodes, .op_name = "END_FINALLY", .op_code = 88, .pop = 1, .push = 0);
88  def_op(.op_obj = ret->opcodes, .op_name = "POP_EXCEPT", .op_code = 89, .pop = 1, .push = -1);
89 
90  ret->have_argument = 90; // Opcodes from here have an argument:
91 
92  store_op00(.op_obj = ret->opcodes, .op_name = "STORE_NAME", .op_code = 90, .pop = 1, .push = 0, .func = NAME_OP); // Operand is in name list
93  name_op(.op_obj = ret->opcodes, .op_name = "DELETE_NAME", .op_code = 91, .pop = 0, .push = 0); // ""
94  varargs_op(.op_obj = ret->opcodes, .op_name = "UNPACK_SEQUENCE", .op_code = 92, .pop = 9, .push = 1); // TOS is number of tuple items
95  jrel_op(.op_obj = ret->opcodes, .op_name = "FOR_ITER", .op_code = 93, .pop = 9, .push = 1);
96 
97  def_op(.op_obj = ret->opcodes, .op_name = "UNPACK_EX", .op_code = 94, .pop = 9, .push = 1); // assignment with a starred target; TOS is #entries
98  // argument has a count
99  store_op00(.op_obj = ret->opcodes, .op_name = "STORE_ATTR", .op_code = 95, .pop = 2, .push = 0, .func = NAME_OP); // Operand is in name list
100  name_op(.op_obj = ret->opcodes, .op_name = "DELETE_ATTR", .op_code = 96, .pop = 1, .push = 0); // ""
101  store_op00(.op_obj = ret->opcodes, .op_name = "STORE_GLOBAL", .op_code = 97, .pop = 1, .push = 0, .func = NAME_OP); // ""
102  name_op(.op_obj = ret->opcodes, .op_name = "DELETE_GLOBAL", .op_code = 98, .pop = 0, .push = 0); // ""
103 
104  // Python 2's DUP_TOPX is gone starting in Python 3.2
105 
106  const_op00(.op_obj = ret->opcodes, .op_name = "LOAD_CONST", .op_code = 100, .pop = 0, .push = 1); // Operand is in const list
107  name_op(.op_obj = ret->opcodes, .op_name = "LOAD_NAME", .op_code = 101, .pop = 0, .push = 1); // Operand is in name list
108  varargs_op(.op_obj = ret->opcodes, .op_name = "BUILD_TUPLE", .op_code = 102, .pop = 9, .push = 1); // TOS is count of tuple items
109  varargs_op(.op_obj = ret->opcodes, .op_name = "BUILD_LIST", .op_code = 103, .pop = 9, .push = 1); // TOS is count of list items
110  varargs_op(.op_obj = ret->opcodes, .op_name = "BUILD_SET", .op_code = 104, .pop = 9, .push = 1); // TOS is count of set items
111  varargs_op(.op_obj = ret->opcodes, .op_name = "BUILD_MAP", .op_code = 105, .pop = 0, .push = 1); // TOS is count of kwarg items
112  name_op(.op_obj = ret->opcodes, .op_name = "LOAD_ATTR", .op_code = 106, .pop = 1, .push = 1); // Operand is in name list
113  compare_op(.op_obj = ret->opcodes, .op_name = "COMPARE_OP", .op_code = 107, .pop = 2, .push = 1); // Comparison operator
114  name_op(.op_obj = ret->opcodes, .op_name = "IMPORT_NAME", .op_code = 108, .pop = 1, .push = 1); // Operand is in name list
115  name_op(.op_obj = ret->opcodes, .op_name = "IMPORT_FROM", .op_code = 109, .pop = 0, .push = 1); // Operand is in name list
116 
117  jrel_op(.op_obj = ret->opcodes, .op_name = "JUMP_FORWARD", .op_code = 110, .pop = 0, .push = 0); // Number of bytes to skip
118  jabs_op(.op_obj = ret->opcodes, .op_name = "JUMP_IF_FALSE_OR_POP", .op_code = 111, .conditional = true); // Target byte offset from beginning of code
119  jabs_op(.op_obj = ret->opcodes, .op_name = "JUMP_IF_TRUE_OR_POP", .op_code = 112, .conditional = true); // ""
120  jabs_op(.op_obj = ret->opcodes, .op_name = "JUMP_ABSOLUTE", .op_code = 113, .pop = 0, .push = 0); // Target byte offset from beginning of code
121  jabs_op(.op_obj = ret->opcodes, .op_name = "POP_JUMP_IF_FALSE", .op_code = 114, .pop = 9, .push = 1, .conditional = true); // ""
122  jabs_op(.op_obj = ret->opcodes, .op_name = "POP_JUMP_IF_TRUE", .op_code = 115, .pop = 9, .push = 1, .conditional = true); // ""
123 
124  name_op(.op_obj = ret->opcodes, .op_name = "LOAD_GLOBAL", .op_code = 116, .pop = 0, .push = 1); // Operand is in name list
125 
126  jabs_op(.op_obj = ret->opcodes, .op_name = "CONTINUE_LOOP", .op_code = 119, .pop = 0, .push = 0); // Target address
127  jrel_op(.op_obj = ret->opcodes, .op_name = "SETUP_LOOP", .op_code = 120, .pop = 0, .push = 0, .conditional = true); // Distance to target address
128  jrel_op(.op_obj = ret->opcodes, .op_name = "SETUP_EXCEPT", .op_code = 121, .pop = 0, .push = 6, .conditional = true); // ""
129  jrel_op(.op_obj = ret->opcodes, .op_name = "SETUP_FINALLY", .op_code = 122, .pop = 0, .push = 6, .conditional = true); // ""
130 
131  local_op(.op_obj = ret->opcodes, .op_name = "LOAD_FAST", .op_code = 124, .pop = 0, .push = 1); // Local variable number
132  store_op00(.op_obj = ret->opcodes, .op_name = "STORE_FAST", .op_code = 125, .pop = 1, .push = 0, .func = LOCAL_OP); // Local variable number
133  local_op(.op_obj = ret->opcodes, .op_name = "DELETE_FAST", .op_code = 126, .pop = 0, .push = 0); // Local variable number
134 
135  def_op00(.op_obj = ret->opcodes, .op_name = "RAISE_VARARGS", .op_code = 130, .pop = 9, .push = 1, .fallthrough = false);
136  // Number of raise arguments (1, 2, or 3)
137  nargs_op(.op_obj = ret->opcodes, .op_name = "CALL_FUNCTION", .op_code = 131, .pop = 9, .push = 1); // #args + (#kwargs << 8)
138 
139  def_op(.op_obj = ret->opcodes, .op_name = "MAKE_FUNCTION", .op_code = 132, .pop = 9, .push = 1); // TOS is number of args if < 3.6
140  varargs_op(.op_obj = ret->opcodes, .op_name = "BUILD_SLICE", .op_code = 133, .pop = 9, .push = 1); // TOS is number of items to pop
141 
142  def_op(.op_obj = ret->opcodes, .op_name = "MAKE_CLOSURE", .op_code = 134, .pop = 9, .push = 1); // TOS is number of items to pop
143  free_op(.op_obj = ret->opcodes, .op_name = "LOAD_CLOSURE", .op_code = 135, .pop = 0, .push = 1);
144  free_op(.op_obj = ret->opcodes, .op_name = "LOAD_DEREF", .op_code = 136, .pop = 0, .push = 1);
145  store_op00(.op_obj = ret->opcodes, .op_name = "STORE_DEREF", .op_code = 137, .pop = 1, .push = 0, .func = FREE_OP);
146  free_op(.op_obj = ret->opcodes, .op_name = "DELETE_DEREF", .op_code = 138, .pop = 0, .push = 0);
147 
148  nargs_op(.op_obj = ret->opcodes, .op_name = "CALL_FUNCTION_VAR", .op_code = 140, .pop = 9, .push = 1); // #args + (#kwargs << 8)
149  nargs_op(.op_obj = ret->opcodes, .op_name = "CALL_FUNCTION_KW", .op_code = 141, .pop = 9, .push = 1); // #args + (#kwargs << 8)
150  nargs_op(.op_obj = ret->opcodes, .op_name = "CALL_FUNCTION_VAR_KW", .op_code = 142, .pop = 9, .push = 1); // #args + (#kwargs << 8)
151 
152  jrel_op(.op_obj = ret->opcodes, .op_name = "SETUP_WITH", .op_code = 143, .pop = 0, .push = 7);
153 
154  def_op(.op_obj = ret->opcodes, .op_name = "LIST_APPEND", .op_code = 145, .pop = 2, .push = 1); // Calls list.append(TOS[-i], TOS).
155  // Used to implement list comprehensions.
156  def_op(.op_obj = ret->opcodes, .op_name = "SET_ADD", .op_code = 146, .pop = 1, .push = 0); // Calls set.add(TOS1[-i], TOS).
157  // Used to implement set comprehensions.
158  def_op(.op_obj = ret->opcodes, .op_name = "MAP_ADD", .op_code = 147, .pop = 2, .push = 1); // Calls dict.setitem(TOS1[-i], TOS, TOS1)
159  // Used to implement dict comprehensions.
160 
161  def_op(.op_obj = ret->opcodes, .op_name = "EXTENDED_ARG", .op_code = 144);
162  ret->extended_arg = 144;
163 
165  add_arg_fmt(ret, "EXTENDED_ARG", format_extended_arg);
166 
167  return ret;
168 }
#define NULL
Definition: cris-opc.c:27
RZ_API void rz_list_purge(RZ_NONNULL RzList *list)
Empties the list without freeing the list pointer.
Definition: list.c:120
pyc_opcodes * new_pyc_opcodes()
Definition: opcode.c:185
void add_arg_fmt(pyc_opcodes *ret, char *op_name, const char *(*formatter)(ut32 oparg))
Definition: opcode.c:234
pyc_opcodes * opcode_3x(void)
Definition: opcode_3x.c:6
#define nargs_op(...)
Definition: opcode.h:171
#define store_op(...)
Definition: opcode.h:145
#define free_op(...)
Definition: opcode.h:141
const char * format_extended_arg(ut32 oparg)
Definition: opcode_arg_fmt.c:6
#define jabs_op(...)
Definition: opcode.h:163
#define local_op(...)
Definition: opcode.h:137
#define const_op00(...)
Definition: opcode.h:154
#define def_op00(...)
Definition: opcode.h:129
#define varargs_op(...)
Definition: opcode.h:149
#define compare_op(...)
Definition: opcode.h:158
#define store_op00(...)
Definition: opcode.h:144
#define jrel_op(...)
Definition: opcode.h:168
#define def_op(...)
Definition: opcode.h:127
@ LOCAL_OP
Definition: opcode.h:32
@ FREE_OP
Definition: opcode.h:33
@ NAME_OP
Definition: opcode.h:31
#define name_op(...)
Definition: opcode.h:133
char * op_name
Definition: opcode.h:38
ut8 have_argument
Definition: opcode.h:47
void *(* version_sig)()
Definition: opcode.h:49
pyc_opcode_object * opcodes
Definition: opcode.h:51
ut8 extended_arg
Definition: opcode.h:46
RzList * opcode_arg_fmt
Definition: opcode.h:50