我们从Python开源项目中,提取了以下24个代码示例,用于说明如何使用dis.hasjrel()。
def calculate_ins_operands(self): """ Instructions like JUMP_FORWARD & SETUP_LOOP uses the operand to refer to other instructions. This reference is an integer denoting the offset/absolute address of the target. This function calculates the values of these operand """ logger.debug('Calculating instruction operands.') for block in self.bb_ordered: addr = block.address for ins in block.instruction_iter(): addr += ins.size if ins.opcode in dis.hasjabs: # ins.argval is a BasicBlock ins.arg = ins.argval.address # TODO # We do not generate EXTENDED_ARG opcode at the moment, # hence size of opcode argument can only be 2 bytes assert ins.arg <= 0xFFFF elif ins.opcode in dis.hasjrel: ins.arg = ins.argval.address - addr # relative jump can USUALLY go forward assert ins.arg >= 0 assert ins.arg <= 0xFFFF
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 encode(self, start, addresses): if self.opcode in dis.hasjabs: arg = addresses[self.arg] elif self.opcode in dis.hasjrel: arg = addresses[self.arg] - (start+3) else: arg = self.arg if arg is None: return bytes([self.opcode]) else: return bytes([self.opcode, arg % 256, arg // 256])
def get_followers(self): """Get the whole list of followers, including the next block.""" followers = set(self.next) # Blocks that must be emitted *after* this one, because of # bytecode offsets (e.g. relative jumps) pointing to them. for inst in self.insts: if inst[0] in PyFlowGraph.hasjrel: followers.add(inst[1]) return followers
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 jump(self): opcode = self.opcode if opcode in dis.hasjrel: return self[1] + self.arg elif opcode in dis.hasjabs: return self.code.address(self.arg)
def is_jump(self): return self.opcode in dis.hasjrel \ or self.opcode in dis.hasjabs
def parse_byte_and_args(self): """ Parse 1 - 3 bytes of bytecode into an instruction and optionally arguments.""" f = self.frame opoffset = f.f_lasti byteCode = ord(f.f_code.co_code[opoffset]) f.f_lasti += 1 byteName = dis.opname[byteCode] arg = None arguments = [] if byteCode >= dis.HAVE_ARGUMENT: arg = f.f_code.co_code[f.f_lasti:f.f_lasti+2] f.f_lasti += 2 intArg = ord(arg[0]) + (ord(arg[1]) << 8) if byteCode in dis.hasconst: arg = f.f_code.co_consts[intArg] elif byteCode in dis.hasfree: if intArg < len(f.f_code.co_cellvars): arg = f.f_code.co_cellvars[intArg] else: var_idx = intArg - len(f.f_code.co_cellvars) arg = f.f_code.co_freevars[var_idx] elif byteCode in dis.hasname: arg = f.f_code.co_names[intArg] elif byteCode in dis.hasjrel: arg = f.f_lasti + intArg elif byteCode in dis.hasjabs: arg = intArg elif byteCode in dis.haslocal: arg = f.f_code.co_varnames[intArg] else: arg = intArg arguments = [arg] return byteName, arguments, opoffset
def _update_label_offsets(code_obj, breakpoint_offset, breakpoint_code_list): """ Update labels for the relative and absolute jump targets :param code_obj: code to modify :param breakpoint_offset: offset for the inserted code :param breakpoint_code_list: size of the inserted code :return: bytes sequence with modified labels; list of tuples (resulting offset, list of code instructions) with information about all inserted pieces of code """ inserted_code = list() # the list with all inserted pieces of code inserted_code.append((breakpoint_offset, breakpoint_code_list)) code_list = list(code_obj) j = 0 while j < len(inserted_code): current_offset, current_code_list = inserted_code[j] offsets_for_modification = [] for offset, op, arg in _unpack_opargs(code_list, inserted_code, j): if arg is not None: if op in dis.hasjrel: # has relative jump target label = offset + 2 + arg if offset < current_offset < label: # change labels for relative jump targets if code was inserted inside offsets_for_modification.append(offset) elif op in dis.hasjabs: # change label for absolute jump if code was inserted before it if current_offset < arg: offsets_for_modification.append(offset) for i in range(0, len(code_list), 2): op = code_list[i] if i in offsets_for_modification and op >= dis.HAVE_ARGUMENT: new_arg = code_list[i + 1] + len(current_code_list) if new_arg <= MAX_BYTE: code_list[i + 1] = new_arg else: # handle bytes overflow if i - 2 > 0 and code_list[i - 2] == EXTENDED_ARG and code_list[i - 1] < MAX_BYTE: # if new argument > 255 and EXTENDED_ARG already exists we need to increase it's argument code_list[i - 1] += 1 else: # if there isn't EXTENDED_ARG operator yet we have to insert the new operator extended_arg_code = [EXTENDED_ARG, new_arg >> 8] inserted_code.append((i, extended_arg_code)) code_list[i + 1] = new_arg & MAX_BYTE code_list = code_list[:current_offset] + current_code_list + code_list[current_offset:] for k in range(len(inserted_code)): offset, inserted_code_list = inserted_code[k] if current_offset < offset: inserted_code[k] = (offset + len(current_code_list), inserted_code_list) j += 1 return bytes(code_list), inserted_code