我们从Python开源项目中,提取了以下17个代码示例,用于说明如何使用dis.hasjabs()。
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 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 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+2) else: arg = self.arg return bytes([self.opcode, arg or 0])
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, op, arg=None): def jump_target(offset): target = offset if op not in hasjabs: target = target - (posn + 3) if target < 0: raise AssertionError("Relative jumps can't go backwards") if target > 0xFFFF: target = offset - (posn + 6) return target def backpatch(offset): target = jump_target(offset) if target > 0xFFFF: raise AssertionError("Forward jump span must be <64K bytes") self.patch_arg(posn, 0, target) self.branch_stack(offset, old_level) if op == FOR_ITER: old_level = self.stack_size = self.stack_size - 1 self.stack_size += 2 else: old_level = self.stack_size self.stack_size -= (op in (JUMP_IF_TRUE_OR_POP, JUMP_IF_FALSE_OR_POP)) posn = self.here() if arg is not None: self.emit_arg(op, jump_target(arg)) self.branch_stack(arg, old_level) lbl = None else: self.emit_arg(op, 0) def lbl(code=None): backpatch(self.here()) if op in (JUMP_FORWARD, JUMP_ABSOLUTE, CONTINUE_LOOP): self.stack_unknown() return lbl
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 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