我们从Python开源项目中,提取了以下50个代码示例,用于说明如何使用dis.opmap()。
def decode_at(self, offset): assert offset < len(self.insBytes) opcode = self.insBytes[offset] if opcode == dis.opmap['EXTENDED_ARG']: raise Exception('EXTENDED_ARG not yet implemented') # Invalid instruction if opcode not in dis.opmap.values(): return Instruction(-1, None, 1) if opcode < dis.HAVE_ARGUMENT: return Instruction(opcode, None, 1) if opcode >= dis.HAVE_ARGUMENT: arg = (self.insBytes[offset + 2] << 8) | self.insBytes[offset + 1] return Instruction(opcode, arg, 3)
def test_expr(expr, allowed_codes): """test_expr(expr, allowed_codes) -> codeobj Test that the expression contains only the listed opcodes. If the expression is valid and contains only allowed codes, return the compiled code object. Otherwise raise a ValueError """ import dis allowed_codes = [dis.opmap[c] for c in allowed_codes] try: c = compile(expr, "", "eval") except SyntaxError: raise ValueError("%s is not a valid expression" % expr) codes = _get_opcodes(c) for code in codes: if code not in allowed_codes: raise ValueError("opcode %s not allowed" % dis.opname[code]) return c
def finalize_opcodes(l): # Not sure why, but opcode.py address has opcode.EXTENDED_ARG # as well as opmap['EXTENDED_ARG'] l['EXTENDED_ARG'] = l['opmap']['EXTENDED_ARG'] # In Python 3.6+ this is 8, but we expect # those opcodes to set that if 'EXTENDED_ARG_SHIFT' not in l: l['EXTENDED_ARG_SHIFT'] = 16 l['ARG_MAX_VALUE'] = (1 << l['EXTENDED_ARG_SHIFT']) - 1 l['EXTENDED_ARG'] = l['opmap']['EXTENDED_ARG'] l['opmap'] = fix_opcode_names(l['opmap']) # Now add in the attributes into the module for op in l['opmap']: l[op] = l['opmap'][op] l['JUMP_OPs'] = frozenset(l['hasjrel'] + l['hasjabs']) l['NOFOLLOW'] = frozenset(l['nofollow']) opcode_check(l) return
def update_sets(l): l['COMPARE_OPS'] = frozenset(l['hascompare']) l['CONDITION_OPS'] = frozenset(l['hascondition']) l['CONST_OPS'] = frozenset(l['hasconst']) l['FREE_OPS'] = frozenset(l['hasfree']) l['JREL_OPS'] = frozenset(l['hasjrel']) l['JABS_OPS'] = frozenset(l['hasjabs']) l['JUMP_UNCONDITONAL'] = frozenset([l['opmap']['JUMP_ABSOLUTE'], l['opmap']['JUMP_FORWARD']]) l['LOOP_OPS'] = frozenset([l['opmap']['SETUP_LOOP']]) l['LOCAL_OPS'] = frozenset(l['haslocal']) l['JUMP_OPS'] = (l['JABS_OPS'] | l['JREL_OPS'] | l['LOOP_OPS'] | l['JUMP_UNCONDITONAL']) l['NAME_OPS'] = frozenset(l['hasname']) l['NARGS_OPS'] = frozenset(l['hasnargs']) l['VARGS_OPS'] = frozenset(l['hasvargs'])
def opcode_check(l): """When the version of Python we are running happens to have the same opcode set as the opcode we are importing, we perform checks to make sure our opcode set matches exactly. """ # Python 2.6 reports 2.6000000000000001 if (abs(PYTHON_VERSION - l['python_version']) <= 0.01 and IS_PYPY == l['is_pypy']): try: import dis opmap = fix_opcode_names(dis.opmap) # print(set(opmap.items()) - set(l['opmap'].items())) # print(set(l['opmap'].items()) - set(opmap.items())) assert all(item in opmap.items() for item in l['opmap'].items()) assert all(item in l['opmap'].items() for item in opmap.items()) except: import sys
def code_all_variables_dynamic(fun): co = fun.func_code len_co_names = len(co.co_names) new_co_names = co.co_names + co.co_varnames new_co_flags = co.co_flags & ~0x02 new_code = '' for end, op, arg in bytecode(fun): if dis.opname[op] == 'STORE_FAST': new_arg = arg + len_co_names new_code += chr(dis.opmap['STORE_NAME']) + \ chr(new_arg % 256) + \ chr(new_arg // 256) elif dis.opname[op] == 'LOAD_FAST': new_arg = arg + len_co_names new_code += chr(dis.opmap['LOAD_NAME']) + \ chr(new_arg % 256) + \ chr(new_arg // 256) else: if arg is None: new_code += chr(op) else: new_code += chr(op) + chr(arg % 256) + chr(arg // 256) func_co = new.code(co.co_argcount, co.co_nlocals, co.co_stacksize, new_co_flags, new_code, co.co_consts, new_co_names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars) return func_co # This is how make statement is implemented: # # make <callable> <name> <tuple>: # <block> # # @make(<callable>, <tuple>) # def <name>(): # <block>
def _opcode(name): """Return the opcode by name from the dis module.""" return dis.opmap[name]
def is_opcode_valid(self): """ Checks whether the instruction is legal. A legal instruction has an opcode which is understood by the CPython VM. """ return self.opcode in dis.opmap.values()
def is_ret(self): """ Checks whether the instruction is a return :return: """ return self.opcode == dis.opmap['RETURN_VALUE']
def get_ins_xref(self, ins, addr): """ An instruction may reference other instruction. Example: SETUP_EXCEPT exc_handler the exception handler is the xref. """ xref_ins = (dis.opmap[x] for x in ('SETUP_LOOP', 'SETUP_EXCEPT', 'SETUP_FINALLY', 'SETUP_WITH')) if ins.opcode in xref_ins: return addr + ins.size + ins.arg else: return None
def create_forwarder_block(self, target): """ Create a new basic block consisting of a `JUMP_ABSOLUTE` instruction to target block :param target: The target basic block to jump to :type target: BasicBlock :return: The new basic block :rtype: BasicBlock """ bb = BasicBlock() ins = Instruction(dis.opmap['JUMP_ABSOLUTE'], target, 3) ins.argval = target bb.add_instruction(ins) return bb
def test_opmap(self): self.assertEqual(dis.opmap["STOP_CODE"], 0) self.assertIn(dis.opmap["LOAD_CONST"], dis.hasconst) self.assertIn(dis.opmap["STORE_NAME"], dis.hasname)
def test_opname(self): self.assertEqual(dis.opname[dis.opmap["LOAD_FAST"]], "LOAD_FAST")
def test_boundaries(self): self.assertEqual(dis.opmap["EXTENDED_ARG"], dis.EXTENDED_ARG) self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT)
def test_opmap(self): self.assertEqual(dis.opmap["NOP"], 9) self.assertIn(dis.opmap["LOAD_CONST"], dis.hasconst) self.assertIn(dis.opmap["STORE_NAME"], dis.hasname)
def find_importer_frame(): """Returns the outer frame importing this "end" module. If this module is being imported by other means than import statement, None is returned. Returns: A frame object or None. """ byte = lambda ch: ord(ch) if PY2 else ch frame = inspect.currentframe() try: while frame: code = frame.f_code lasti = frame.f_lasti if byte(code.co_code[lasti]) == dis.opmap['IMPORT_NAME']: # FIXME: Support EXTENDED_ARG. arg = ( byte(code.co_code[lasti + 1]) + byte(code.co_code[lasti + 2]) * 256) name = code.co_names[arg] if name == 'end': break end end frame = frame.f_back end return frame finally: del frame end
def test_stack_effect(self): self.assertEqual(_opcode.stack_effect(dis.opmap['POP_TOP']), -1) self.assertEqual(_opcode.stack_effect(dis.opmap['DUP_TOP_TWO']), 2) self.assertEqual(_opcode.stack_effect(dis.opmap['BUILD_SLICE'], 0), -1) self.assertEqual(_opcode.stack_effect(dis.opmap['BUILD_SLICE'], 1), -1) self.assertEqual(_opcode.stack_effect(dis.opmap['BUILD_SLICE'], 3), -2) self.assertRaises(ValueError, _opcode.stack_effect, 30000) self.assertRaises(ValueError, _opcode.stack_effect, dis.opmap['BUILD_SLICE']) self.assertRaises(ValueError, _opcode.stack_effect, dis.opmap['POP_TOP'], 0)
def init_opdata(l, from_mod, version=None, is_pypy=False): """Sets up a number of the structures found in Python's opcode.py. Python opcode.py routines assign attributes to modules. In order to do this in a modular way here, the local dictionary for the module is passed. """ if version: l['python_version'] = version l['is_pypy'] = is_pypy l['cmp_op'] = cmp_op l['HAVE_ARGUMENT'] = HAVE_ARGUMENT if version <= 3.5: l['findlinestarts'] = findlinestarts l['findlabels'] = findlabels l['get_jump_targets'] = get_jump_targets l['get_jump_target_maps'] = get_jump_target_maps else: l['findlinestarts'] = wordcode.findlinestarts l['findlabels'] = wordcode.findlabels l['get_jump_targets'] = wordcode.get_jump_targets l['get_jump_target_maps'] = wordcode.get_jump_target_maps l['opmap'] = deepcopy(from_mod.opmap) l['opname'] = deepcopy(from_mod.opname) for field in fields2copy: l[field] = list(getattr(from_mod, field))
def def_op(l, op_name, opcode, pop=-2, push=-2, fallthrough=True): l['opname'][opcode] = op_name l['opmap'][op_name] = opcode l['oppush'][opcode] = push l['oppop'][opcode] = pop if not fallthrough: l['nofollow'].append(opcode)
def rm_op(l, name, op): """Remove an opcode. This is used when basing a new Python release off of another one, and there is an opcode that is in the old release that was removed in the new release. We are pretty aggressive about removing traces of the op. """ # opname is an array, so we need to keep the position in there. l['opname'][op] = '<%s>' % op if op in l['hasconst']: l['hasconst'].remove(op) if op in l['hascompare']: l['hascompare'].remove(op) if op in l['hascondition']: l['hascondition'].remove(op) if op in l['hasfree']: l['hasfree'].remove(op) if op in l['hasjabs']: l['hasjabs'].remove(op) if op in l['hasname']: l['hasname'].remove(op) if op in l['hasjrel']: l['hasjrel'].remove(op) if op in l['haslocal']: l['haslocal'].remove(op) if op in l['hasname']: l['hasname'].remove(op) if op in l['hasnargs']: l['hasnargs'].remove(op) if op in l['hasvargs']: l['hasvargs'].remove(op) if op in l['nofollow']: l['nofollow'].remove(op) assert l['opmap'][name] == op del l['opmap'][name]
def fix_opcode_names(opmap): """ Python stupidly named some OPCODES with a + which prevents using opcode name directly as an attribute, e.g. SLICE+3. So we turn that into SLICE_3 so we can then use opcode_23.SLICE_3. Later Python's fix this. """ return dict([(k.replace('+', '_'), v) for (k, v) in opmap.items()])
def update_pj2(g, l): g.update({'PJIF': l['opmap']['JUMP_IF_FALSE']}) g.update({'PJIT': l['opmap']['JUMP_IF_TRUE']}) update_sets(l)
def dump_opcodes(opmap): """Utility for dumping opcodes""" op2name = {} for k in opmap.keys(): op2name[opmap[k]] = k for i in sorted(op2name.keys()): print("%-3s %s" % (str(i), op2name[i]))