def __add__(self, addend): from peachpy.x86_64.registers import GeneralPurposeRegister64, GeneralPurposeRegister32 from peachpy.util import is_int, is_sint32 if is_int(addend): if not is_sint32(addend): raise ValueError("The addend value (%d) is not representable as a signed 32-bit integer" % addend) return MemoryAddress(self.base, self.index, self.scale, self.displacement + addend) elif isinstance(addend, (GeneralPurposeRegister64, GeneralPurposeRegister32)): if self.base is not None: raise TypeError("Can not add a general-purpose register to a memory operand with existing base") if self.index.size != addend.size: raise TypeError("Index (%s) and addend (%s) registers have different size" % (str(self.index), str(addend))) return MemoryAddress(addend, self.index, self.scale, self.displacement) elif isinstance(addend, MemoryAddress): if self.base is not None and addend.base is not None: raise ValueError("Can not add memory address: both address expressions use base registers") if self.index is not None and addend.index is not None: raise ValueError("Can not add memory address: both address expressions use index registers") sum_base = self.base if self.base is not None else addend.base (sum_index, sum_scale) = (self.index, self.scale) \ if self.index is not None else (addend.index, addend.scale) return MemoryAddress(sum_base, sum_index, sum_scale, self.displacement + addend.displacement) else: raise TypeError("Can not add %s: unsupported addend type" % str(addend))
def _encode_label_branch(self, address, label_address=None, long_encoding=False): if label_address is None: encodings = [encode(0) for (_, encode) in self.encodings] else: encodings = [] from peachpy.x86_64.encoding import Flags from peachpy.util import is_sint8, is_sint32 for (flags, encode) in self.encodings: offset = label_address - (address + len(encode(0))) if flags & Flags.Rel8Label != 0 and is_sint8(offset) or \ flags & Flags.Rel32Label != 0 and is_sint32(offset): encodings.append(encode(offset)) if not encodings: raise ValueError("Can not encode offset to label %s" % self.label_name) assert len( encodings ) <= 2, "At most 2 encodings expected for branch instructions with immediate code offset" if len(encodings) == 1: return True, encodings[0] else: if long_encoding: return True, max(encodings, key=len) else: return False, min(encodings, key=len)
def __init__(self, base=None, index=None, scale=None, displacement=0): from peachpy.x86_64.registers import GeneralPurposeRegister64, GeneralPurposeRegister32 from peachpy.util import is_int, is_sint32 # Check individual arguments if base is not None and not isinstance(base, (GeneralPurposeRegister32, GeneralPurposeRegister64)): raise TypeError("Base register must be a 32- or 64-bit general-purpose register") if index is not None and not isinstance(index, (GeneralPurposeRegister32, GeneralPurposeRegister64)): raise TypeError("Index register must be a 32- or 64-bit general-purpose register") if scale is not None and not is_int(scale): raise TypeError("Scale must be an integer") if scale is not None and int(scale) not in {1, 2, 4, 8}: raise TypeError("Scale must be 1, 2, 4, or 8") if not is_sint32(displacement): raise ValueError("Displacement value (%s) is not representable as a signed 32-bit integer" % str(displacement)) # Check relations of arguments if scale is not None and index is None or scale is None and index is not None: raise ValueError("Either both of neither of scale and index must be defined") if base is not None and index is not None and base.size != index.size: raise TypeError("Base (%s) and index (%s) registers have different size" % (str(base), str(index))) if index is None and base is None: raise ValueError("Either base or index * scale must be specified") self.base = base self.index = index self.scale = None if scale is None else int(scale) self.displacement = int(displacement)
def __init__(self, base=None, index=None, scale=None, displacement=0): from peachpy.x86_64.registers import GeneralPurposeRegister64, \ XMMRegister, YMMRegister, ZMMRegister, MaskedRegister from peachpy.util import is_int, is_sint32 # Check individual arguments if base is not None and not isinstance(base, GeneralPurposeRegister64): raise TypeError("Base register must be a 64-bit general-purpose register") if index is not None and \ not isinstance(index, (GeneralPurposeRegister64, XMMRegister, YMMRegister, ZMMRegister)) and not \ (isinstance(index, MaskedRegister) and isinstance(index.register, (XMMRegister, YMMRegister, ZMMRegister)) and not index.mask.is_zeroing): raise TypeError("Index register must be a 64-bit general-purpose register or an XMM/YMM/ZMM register") if scale is not None and not is_int(scale): raise TypeError("Scale must be an integer") if scale is not None and int(scale) not in {1, 2, 4, 8}: raise TypeError("Scale must be 1, 2, 4, or 8") if not is_sint32(displacement): raise ValueError("Displacement value (%s) is not representable as a signed 32-bit integer" % str(displacement)) # Check relations of arguments if scale is not None and index is None or scale is None and index is not None: raise ValueError("Either both of neither of scale and index must be defined") if index is None and base is None: raise ValueError("Either base or index * scale must be specified") self.base = base self.index = index self.scale = None if scale is None else int(scale) self.displacement = int(displacement)
def _encode_label_branch(self, address, label_address=None, long_encoding=False): if label_address is None: encodings = [encode(0) for (_, encode) in self.encodings] else: encodings = [] from peachpy.x86_64.encoding import Flags from peachpy.util import is_sint8, is_sint32 for (flags, encode) in self.encodings: offset = label_address - (address + len(encode(0))) if ( flags & Flags.Rel8Label != 0 and is_sint8(offset) or flags & Flags.Rel32Label != 0 and is_sint32(offset) ): encodings.append(encode(offset)) if not encodings: raise ValueError("Can not encode offset to label %s" % self.label_name) assert len(encodings) <= 2, "At most 2 encodings expected for branch instructions with immediate code offset" if len(encodings) == 1: return True, encodings[0] else: if long_encoding: return True, max(encodings, key=len) else: return False, min(encodings, key=len)
def __sub__(self, minuend): from peachpy.util import is_int, is_sint32 if is_int(minuend): if not is_sint32(-minuend): raise ValueError("The addend value (%d) is not representable as a signed 32-bit integer" % minuend) return MemoryAddress(self.base, self.index, self.scale, self.displacement - minuend) else: raise TypeError("Can not add %s: unsupported addend type" % str(minuend))
def __init__(self, type, offset, size, symbol, is_pc_relative=False): from peachpy.util import is_sint32 assert is_sint32(offset) assert offset >= 0 assert size in [1, 2, 4, 8] from peachpy.formats.macho.section import Section assert symbol is None or isinstance(symbol, (Section, Symbol)) self.type = type self.offset = offset self.size = size self.symbol = symbol self.is_pc_relative = is_pc_relative
def is_rel32(operand): from peachpy.util import is_sint32 return isinstance(operand, RIPRelativeOffset) and is_sint32(operand.offset)