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)
python类opmap()的实例源码
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 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 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["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["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 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 _opcode(name):
"""Return the opcode by name from the dis module."""
return dis.opmap[name]
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_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)