def test_expr(expr, allowed_codes):
"""test_expr(expr) -> 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
"""
try:
c = compile(expr, "", "eval")
except:
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
python类opname()的实例源码
def dump(self, io=None):
if io:
save = sys.stdout
sys.stdout = io
pc = 0
for t in self.insts:
opname = t[0]
if opname == "SET_LINENO":
print
if len(t) == 1:
print "\t", "%3d" % pc, opname
pc = pc + 1
else:
print "\t", "%3d" % pc, opname, t[1]
pc = pc + 3
if io:
sys.stdout = save
def makeByteCode(self):
assert self.stage == CONV
self.lnotab = lnotab = LineAddrTable()
for t in self.insts:
opname = t[0]
if len(t) == 1:
lnotab.addCode(self.opnum[opname])
else:
oparg = t[1]
if opname == "SET_LINENO":
lnotab.nextLine(oparg)
continue
hi, lo = twobyte(oparg)
try:
lnotab.addCode(self.opnum[opname], lo, hi)
except ValueError:
print opname, oparg
print self.opnum[opname], lo, hi
raise
self.stage = DONE
def get_opcode(self):
# Based on the settings decide to show the line-by-line trace
# Get the current line being executed
ip = self.__ip
op = self.__code[self.__ip]
ip += 1
opmethod = "execute_%s" % dis.opname[op]
oparg = None
if op >= dis.HAVE_ARGUMENT:
low = self.__code[ip]
high = self.__code[ip + 1]
oparg = (high << 8) | low
return opmethod, oparg
def dump(self, io=None):
if io:
save = sys.stdout
sys.stdout = io
pc = 0
for t in self.insts:
opname = t[0]
if opname == "SET_LINENO":
print()
if len(t) == 1:
print("\t", "%3d" % pc, opname)
pc = pc + 1
else:
print("\t", "%3d" % pc, opname, t[1])
pc = pc + 3
if io:
sys.stdout = save
def makeByteCode(self):
assert self.stage == CONV
self.lnotab = lnotab = LineAddrTable()
for t in self.insts:
opname = t[0]
if len(t) == 1:
lnotab.addCode(self.opnum[opname])
else:
oparg = t[1]
if opname == "SET_LINENO":
lnotab.nextLine(oparg)
continue
hi, lo = twobyte(oparg)
try:
lnotab.addCode(self.opnum[opname], lo, hi)
except ValueError:
print(opname, oparg)
print(self.opnum[opname], lo, hi)
raise
self.stage = DONE
def dump(self, io=None):
if io:
save = sys.stdout
sys.stdout = io
pc = 0
for t in self.insts:
opname = t[0]
if opname == "SET_LINENO":
print
if len(t) == 1:
print "\t", "%3d" % pc, opname
pc = pc + 1
else:
print "\t", "%3d" % pc, opname, t[1]
pc = pc + 3
if io:
sys.stdout = save
def dump(self, io=None):
if io:
save = sys.stdout
sys.stdout = io
pc = 0
for t in self.insts:
opname = t[0]
if opname == "SET_LINENO":
print
if len(t) == 1:
print "\t", "%3d" % pc, opname
pc = pc + 1
else:
print "\t", "%3d" % pc, opname, t[1]
pc = pc + 3
if io:
sys.stdout = save
def makeByteCode(self):
assert self.stage == CONV
self.lnotab = lnotab = LineAddrTable()
for t in self.insts:
opname = t[0]
if len(t) == 1:
lnotab.addCode(self.opnum[opname])
else:
oparg = t[1]
if opname == "SET_LINENO":
lnotab.nextLine(oparg)
continue
hi, lo = twobyte(oparg)
try:
lnotab.addCode(self.opnum[opname], lo, hi)
except ValueError:
print opname, oparg
print self.opnum[opname], lo, hi
raise
self.stage = DONE
def dump(self, io=None):
if io:
save = sys.stdout
sys.stdout = io
pc = 0
for t in self.insts:
opname = t[0]
if opname == "SET_LINENO":
print
if len(t) == 1:
print "\t", "%3d" % pc, opname
pc = pc + 1
else:
print "\t", "%3d" % pc, opname, t[1]
pc = pc + 3
if io:
sys.stdout = save
def makeByteCode(self):
assert self.stage == CONV
self.lnotab = lnotab = LineAddrTable()
for t in self.insts:
opname = t[0]
if len(t) == 1:
lnotab.addCode(self.opnum[opname])
else:
oparg = t[1]
if opname == "SET_LINENO":
lnotab.nextLine(oparg)
continue
hi, lo = twobyte(oparg)
try:
lnotab.addCode(self.opnum[opname], lo, hi)
except ValueError:
print opname, oparg
print self.opnum[opname], lo, hi
raise
self.stage = DONE
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 dump(self, io=None):
if io:
save = sys.stdout
sys.stdout = io
pc = 0
for t in self.insts:
opname = t[0]
if opname == "SET_LINENO":
print
if len(t) == 1:
print "\t", "%3d" % pc, opname
pc = pc + 1
else:
print "\t", "%3d" % pc, opname, t[1]
pc = pc + 3
if io:
sys.stdout = save
def makeByteCode(self):
assert self.stage == CONV
self.lnotab = lnotab = LineAddrTable()
for t in self.insts:
opname = t[0]
if len(t) == 1:
lnotab.addCode(self.opnum[opname])
else:
oparg = t[1]
if opname == "SET_LINENO":
lnotab.nextLine(oparg)
continue
hi, lo = twobyte(oparg)
try:
lnotab.addCode(self.opnum[opname], lo, hi)
except ValueError:
print opname, oparg
print self.opnum[opname], lo, hi
raise
self.stage = DONE
def _get_instructions(code_obj):
if hasattr(dis, 'get_instructions'):
return list(dis.get_instructions(code_obj))
instructions = []
instruction = None
for byte in code_obj.co_code:
byte = _six_ord(byte)
if instruction is None:
instruction = [byte]
else:
instruction.append(byte)
if instruction[0] < dis.HAVE_ARGUMENT or len(instruction) == 3:
op_code = instruction[0]
op_name = dis.opname[op_code]
if instruction[0] < dis.HAVE_ARGUMENT:
instructions.append(_Instruction(op_code, op_name, None, None))
else:
arg = instruction[1]
instructions.append(_Instruction(op_code, op_name, arg, arg))
instruction = None
return instructions
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 parse_byte_and_args(self):
code = self.f_code
opcode = code.co_code[self.f_lasti]
self.f_lasti = self.f_lasti + 1
if opcode >= dis.HAVE_ARGUMENT:
int_arg = ( code.co_code[self.f_lasti]
+ (code.co_code[self.f_lasti+1] << 8))
self.f_lasti = self.f_lasti + 2
if opcode in dis.hasconst:
arg = code.co_consts[int_arg]
elif opcode in dis.hasfree:
if int_arg < len(code.co_cellvars):
arg = code.co_cellvars[int_arg]
else:
arg = code.co_freevars[int_arg - len(code.co_cellvars)]
elif opcode in dis.hasname:
arg = code.co_names[int_arg]
elif opcode in dis.haslocal:
arg = code.co_varnames[int_arg]
elif opcode in dis.hasjrel:
arg = self.f_lasti + int_arg
else:
arg = int_arg
return dis.opname[opcode], (arg,)
return dis.opname[opcode], ()
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 flattenGraph(self):
"""Arrange the blocks in order and resolve jumps"""
assert self.stage == RAW
self.insts = insts = []
pc = 0
begin = {}
end = {}
for b in self.getBlocksInOrder():
begin[b] = pc
for inst in b.getInstructions():
insts.append(inst)
if len(inst) == 1:
pc = pc + 1
elif inst[0] != "SET_LINENO":
# arg takes 2 bytes
pc = pc + 3
end[b] = pc
pc = 0
for i in range(len(insts)):
inst = insts[i]
if len(inst) == 1:
pc = pc + 1
elif inst[0] != "SET_LINENO":
pc = pc + 3
opname = inst[0]
if opname in self.hasjrel:
oparg = inst[1]
offset = begin[oparg] - pc
insts[i] = opname, offset
elif opname in self.hasjabs:
insts[i] = opname, begin[inst[1]]
self.stage = FLAT
def convertArgs(self):
"""Convert arguments from symbolic to concrete form"""
assert self.stage == FLAT
self.consts.insert(0, self.docstring)
self.sort_cellvars()
for i in range(len(self.insts)):
t = self.insts[i]
if len(t) == 2:
opname, oparg = t
conv = self._converters.get(opname, None)
if conv:
self.insts[i] = opname, conv(self, oparg)
self.stage = CONV
def isJump(opname):
if opname[:4] == 'JUMP':
return 1
def _get_base_class_names(frame):
"""Get baseclass names from the code object"""
co, lasti = frame.f_code, frame.f_lasti
code = co.co_code
i = 0
extended_arg = 0
extends = []
while i <= lasti:
c = code[i]
op = ord(c)
i += 1
if op >= dis.HAVE_ARGUMENT:
oparg = ord(code[i]) + ord(code[i+1])*256 + extended_arg
extended_arg = 0
i += 2
if op == dis.EXTENDED_ARG:
extended_arg = oparg*int(65536)
if op in dis.hasconst:
if type(co.co_consts[oparg]) == str:
extends = []
elif op in dis.hasname:
if dis.opname[op] == 'LOAD_NAME':
extends.append(('name', co.co_names[oparg]))
if dis.opname[op] == 'LOAD_ATTR':
extends.append(('attr', co.co_names[oparg]))
items = []
previous_item = []
for t, s in extends:
if t == 'name':
if previous_item:
items.append(previous_item)
previous_item = [s]
else:
previous_item += [s]
if previous_item:
items.append(previous_item)
return items
def get_opcode(self):
# Based on the settings decide to show the line-by-line trace
# Get the current line being executed
current_lineno = self.__exec_frame.line_no_obj.line_number(self.__exec_frame.ip)
ip = self.__exec_frame.ip
# Update the line number only if the currently executing line has changed.
if self.__exec_frame.line_no_obj.currently_executing_line is None or \
self.__exec_frame.line_no_obj.currently_executing_line != current_lineno:
self.__exec_frame.line_no_obj.currently_executing_line = current_lineno
self.__exec_frame.line_no_obj.currently_executing_line = current_lineno
if self.__config.show_line_execution:
current_line = self.__exec_frame.line_no_obj.get_source_line(current_lineno)
print("Execution Line: %s" % current_line)
op = self.__exec_frame.program[self.__exec_frame.ip]
ip += 1
opmethod = "execute_%s" % dis.opname[op]
oparg = None
if op >= dis.HAVE_ARGUMENT:
low = self.__exec_frame.program[ip]
high = self.__exec_frame.program[ip + 1]
oparg = (high << 8) | low
return opmethod, oparg, current_lineno
def execute_COMPARE_OP(self, compare_op):
"""
Performs a Boolean operation. The operation name can be found in cmp_op[opname].
"""
w = self.__exec_frame.pop()
v = self.__exec_frame.pop()
if len(COMPARE_OPERATORS) < compare_op:
raise NotImplementedError("Compare Op %s not implemented" % compare_op)
value = COMPARE_OPERATORS[compare_op](v, w)
self.__exec_frame.append(value)
def _block_stack_repr(self, block_stack):
"""Get a string version of `block_stack`, for debugging."""
blocks = ", ".join(
["(%s, %r)" % (dis.opname[b[0]], b[1]) for b in block_stack]
)
return "[" + blocks + "]"
def _get_base_class_names(frame):
"""Get baseclass names from the code object"""
co, lasti = frame.f_code, frame.f_lasti
code = co.co_code
i = 0
extended_arg = 0
extends = []
while i <= lasti:
c = code[i]
op = ord(c)
i += 1
if op >= dis.HAVE_ARGUMENT:
oparg = ord(code[i]) + ord(code[i+1])*256 + extended_arg
extended_arg = 0
i += 2
if op == dis.EXTENDED_ARG:
extended_arg = oparg*int(65536)
if op in dis.hasconst:
if type(co.co_consts[oparg]) == str:
extends = []
elif op in dis.hasname:
if dis.opname[op] == 'LOAD_NAME':
extends.append(('name', co.co_names[oparg]))
if dis.opname[op] == 'LOAD_ATTR':
extends.append(('attr', co.co_names[oparg]))
items = []
previous_item = []
for t, s in extends:
if t == 'name':
if previous_item:
items.append(previous_item)
previous_item = [s]
else:
previous_item += [s]
if previous_item:
items.append(previous_item)
return items
def __init__(self, opcode, arg, size):
# Numeric code for operation, corresponding to the opcode values
self.opcode = opcode
# Numeric argument to operation(if any), otherwise None
self.arg = arg
# The size of the instruction including the arguement
self.size = size
# Resolved arg value (if known), otherwise same as arg
self.argval = arg
# Human readable name for operation
self.mnemonic = dis.opname[self.opcode]
def test_opname(self):
self.assertEqual(dis.opname[dis.opmap["LOAD_FAST"]], "LOAD_FAST")
def flattenGraph(self):
"""Arrange the blocks in order and resolve jumps"""
assert self.stage == RAW
self.insts = insts = []
pc = 0
begin = {}
end = {}
for b in self.getBlocksInOrder():
begin[b] = pc
for inst in b.getInstructions():
insts.append(inst)
if len(inst) == 1:
pc = pc + 1
elif inst[0] != "SET_LINENO":
# arg takes 2 bytes
pc = pc + 3
end[b] = pc
pc = 0
for i in range(len(insts)):
inst = insts[i]
if len(inst) == 1:
pc = pc + 1
elif inst[0] != "SET_LINENO":
pc = pc + 3
opname = inst[0]
if opname in self.hasjrel:
oparg = inst[1]
offset = begin[oparg] - pc
insts[i] = opname, offset
elif opname in self.hasjabs:
insts[i] = opname, begin[inst[1]]
self.stage = FLAT
def convertArgs(self):
"""Convert arguments from symbolic to concrete form"""
assert self.stage == FLAT
self.consts.insert(0, self.docstring)
self.sort_cellvars()
for i in range(len(self.insts)):
t = self.insts[i]
if len(t) == 2:
opname, oparg = t
conv = self._converters.get(opname, None)
if conv:
self.insts[i] = opname, conv(self, oparg)
self.stage = CONV