Пример #1
0
def check_operand(operand):
    """Validates operand object as an instruction operand and converts it to a standard form"""

    from peachpy.x86_64.registers import Register
    from peachpy.x86_64.pseudo import Label
    from peachpy.x86_64.function import LocalVariable
    from peachpy import Constant, Argument
    from peachpy.util import is_int, is_int64
    if isinstance(operand, (Register, Constant, MemoryOperand, LocalVariable,
                            Argument, RIPRelativeOffset, Label)):
        return operand
    elif is_int(operand):
        if not is_int64(operand):
            raise ValueError(
                "The immediate operand %d is not representable as a 64-bit value"
            )
        return operand
    elif isinstance(operand, list):
        if len(operand) != 1:
            raise ValueError(
                "Memory operands must be represented by a list with only one element"
            )
        return MemoryOperand(operand[0])
    else:
        raise TypeError("Unsupported operand: %s" % str(operand))
Пример #2
0
def check_operand(operand):
    """Validates operand object as an instruction operand and converts it to a standard form"""

    from peachpy.x86_64.registers import Register, MaskedRegister
    from peachpy.x86_64.pseudo import Label
    from peachpy.x86_64.function import LocalVariable
    from peachpy.literal import Constant
    from peachpy import Argument
    from peachpy.util import is_int, is_int64
    if isinstance(operand, (Register, MaskedRegister, Constant, MemoryOperand, LocalVariable, Argument,
                            RIPRelativeOffset, Label)):
        return operand
    elif is_int(operand):
        if not is_int64(operand):
            raise ValueError("The immediate operand %d is not representable as a 64-bit value")
        return operand
    elif isinstance(operand, list):
        if len(operand) != 1:
            raise ValueError("Memory operands must be represented by a list with only one element")
        return MemoryOperand(operand[0])
    elif isinstance(operand, set):
        if len(operand) != 1:
            raise ValueError("Rounding control & suppress-all-errors operands must be represented by a set "
                             "with only one element")
        return next(iter(operand))
    else:
        raise TypeError("Unsupported operand: %s" % str(operand))
Пример #3
0
def format_operand(operand, assembly_format):
    assert assembly_format in {"peachpy", "gas", "nasm", "go"}, \
        "Supported assembly formats are 'peachpy', 'gas', 'nasm', 'go'"

    immediate_prefix_map = {"peachpy": "", "gas": "$", "nasm": "", "go": "$"}

    from peachpy.util import is_int64
    if is_int64(operand):
        return immediate_prefix_map[assembly_format] + str(operand)
    else:
        return operand.format(assembly_format)
Пример #4
0
def format_operand_type(operand):
    """Returns string representation of the operand type in assembly language"""
    from peachpy.x86_64.registers import GeneralPurposeRegister64, GeneralPurposeRegister32, GeneralPurposeRegister16,\
        GeneralPurposeRegister8, MMXRegister, XMMRegister, YMMRegister,\
        al, ax, eax, rax, cl, xmm0
    from peachpy.x86_64.pseudo import Label
    from peachpy.util import is_int64, is_int32, is_int16, is_int8
    if is_int8(operand):
        return "imm8"
    elif is_int16(operand):
        return "imm16"
    elif is_int32(operand):
        return "imm32"
    elif is_int64(operand):
        return "imm64"
    elif al == operand:
        return "al"
    elif ax == operand:
        return "ax"
    elif eax == operand:
        return "eax"
    elif rax == operand:
        return "rax"
    elif cl == operand:
        return "cl"
    elif xmm0 == operand:
        return "xmm0"
    elif isinstance(operand, GeneralPurposeRegister64):
        return "r64"
    elif isinstance(operand, GeneralPurposeRegister32):
        return "r32"
    elif isinstance(operand, GeneralPurposeRegister16):
        return "r16"
    elif isinstance(operand, GeneralPurposeRegister8):
        return "r8"
    elif isinstance(operand, MMXRegister):
        return "mm"
    elif isinstance(operand, XMMRegister):
        return "xmm"
    elif isinstance(operand, YMMRegister):
        return "ymm"
    elif isinstance(operand, MemoryOperand):
        if operand.size is None:
            return "m"
        else:
            return "m" + str(operand.size)
    elif isinstance(operand, Label):
        return "rel"
    else:
        return operand.__class__.__name__
Пример #5
0
def format_operand_type(operand):
    """Returns string representation of the operand type in assembly language"""
    from peachpy.x86_64.registers import GeneralPurposeRegister64, GeneralPurposeRegister32, GeneralPurposeRegister16,\
        GeneralPurposeRegister8, MMXRegister, XMMRegister, YMMRegister,\
        al, ax, eax, rax, cl, xmm0
    from peachpy.x86_64.pseudo import Label
    from peachpy.util import is_int64, is_int32, is_int16, is_int8
    if is_int8(operand):
        return "imm8"
    elif is_int16(operand):
        return "imm16"
    elif is_int32(operand):
        return "imm32"
    elif is_int64(operand):
        return "imm64"
    elif al == operand:
        return "al"
    elif ax == operand:
        return "ax"
    elif eax == operand:
        return "eax"
    elif rax == operand:
        return "rax"
    elif cl == operand:
        return "cl"
    elif xmm0 == operand:
        return "xmm0"
    elif isinstance(operand, GeneralPurposeRegister64):
        return "r64"
    elif isinstance(operand, GeneralPurposeRegister32):
        return "r32"
    elif isinstance(operand, GeneralPurposeRegister16):
        return "r16"
    elif isinstance(operand, GeneralPurposeRegister8):
        return "r8"
    elif isinstance(operand, MMXRegister):
        return "mm"
    elif isinstance(operand, XMMRegister):
        return "xmm"
    elif isinstance(operand, YMMRegister):
        return "ymm"
    elif isinstance(operand, MemoryOperand):
        if operand.size is None:
            return "m"
        else:
            return "m" + str(operand.size)
    elif isinstance(operand, Label):
        return "rel"
    else:
        return operand.__class__.__name__
Пример #6
0
def format_operand(operand, assembly_format):
    assert assembly_format in {"peachpy", "gnu", "nasm", "go"}, \
        "Supported assembly formats are 'peachpy', 'gnu', 'nasm', 'go'"

    immediate_prefix_map = {
        "peachpy": "",
        "gnu": "$",
        "nasm": "",
        "go": "$"
    }

    from peachpy.util import is_int64
    if is_int64(operand):
        return immediate_prefix_map[assembly_format] + str(operand)
    else:
        return operand.format(assembly_format)
Пример #7
0
def check_operand(operand):
    """Validates operand object as an instruction operand and converts it to a standard form"""

    from peachpy.x86_64.registers import Register, MaskedRegister
    from peachpy.x86_64.pseudo import Label
    from peachpy.x86_64.function import LocalVariable
    from peachpy.literal import Constant
    from peachpy import Argument
    from peachpy.util import is_int, is_int64
    from copy import copy, deepcopy
    if isinstance(operand, Register):
        return copy(operand)
    elif isinstance(operand, (MaskedRegister, MemoryOperand)):
        return deepcopy(operand)
    elif isinstance(operand, (Argument, RIPRelativeOffset, Label)):
        return operand
    elif is_int(operand):
        if not is_int64(operand):
            raise ValueError(
                "The immediate operand %d is not representable as a 64-bit value"
            )
        return operand
    elif isinstance(operand, list):
        if len(operand) != 1:
            raise ValueError(
                "Memory operands must be represented by a list with only one element"
            )
        return MemoryOperand(operand[0])
    elif isinstance(operand, Constant):
        from copy import copy, deepcopy
        operand = copy(operand)
        import peachpy.common.function
        if peachpy.common.function.active_function:
            operand.name = deepcopy(
                operand.name,
                peachpy.common.function.active_function._names_memo)
        return MemoryOperand(operand)
    elif isinstance(operand, LocalVariable):
        return MemoryOperand(operand)
    elif isinstance(operand, set):
        if len(operand) != 1:
            raise ValueError(
                "Rounding control & suppress-all-errors operands must be represented by a set "
                "with only one element")
        return next(iter(operand))
    else:
        raise TypeError("Unsupported operand: %s" % str(operand))
Пример #8
0
 def _uint64xN(name, n, *args):
     from peachpy.util import is_int, is_int64
     assert is_int(n)
     args = [arg for arg in args if arg is not None]
     if len(args) == 0:
         raise ValueError("At least one constant value must be specified")
     if len(args) != 1 and len(args) != n:
         raise ValueError("Either 1 or %d values must be specified" % n)
     for i, number in enumerate(args):
         if not is_int(number):
             raise TypeError("The value %s is not an integer" % str(number))
         if not is_int64(number):
             raise ValueError("The number %d is not a 64-bit integer" % number)
         if number < 0:
             args[i] += 0x10000000000000000
     if len(args) == 1:
         args = [args[0]] * n
     return Constant(8 * n, n, tuple(args), uint64_t, name)
Пример #9
0
 def _uint64xN(name, n, *args):
     from peachpy.util import is_int, is_int64
     assert is_int(n)
     args = [arg for arg in args if arg is not None]
     if len(args) == 0:
         raise ValueError("At least one constant value must be specified")
     if len(args) != 1 and len(args) != n:
         raise ValueError("Either 1 or %d values must be specified" % n)
     for i, number in enumerate(args):
         if not is_int(number):
             raise TypeError("The value %s is not an integer" % str(number))
         if not is_int64(number):
             raise ValueError("The number %d is not a 64-bit integer" % number)
         if number < 0:
             args[i] += 0x10000000000000000
     if len(args) == 1:
         args = [args[0]] * n
     return Constant(8 * n, n, tuple(args), uint64_t, name)
Пример #10
0
    def __init__(self, *args, **kwargs):
        from peachpy.x86_64.function import active_function
        from peachpy.x86_64.registers import GeneralPurposeRegister, MMXRegister, XMMRegister, YMMRegister

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level() > 0:
            origin = inspect.stack()
        super(RETURN, self).__init__("RETURN", origin=origin)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) == 0:
            # It is not an error to return nothing from a function with a return type
            self.in_regs = tuple()
            self.out_regs = tuple()
            self.out_operands = tuple()
        elif len(self.operands) == 1:
            # It is an error to return something from a void function
            from peachpy.util import is_int64, int_size
            if active_function.result_type is None:
                raise ValueError("Void function should not return a value")
            if active_function.result_type.is_integer or active_function.result_type.is_pointer:
                if is_int64(self.operands[0]):
                    if active_function.result_type.size is None and int_size(self.operands[0]) > 4 or\
                        active_function.result_type.size is not None and \
                            active_function.result_type.size < int_size(self.operands[0]):
                        raise ValueError("Value {0} can not be represented with return type {1}".
                                         format(str(self.operands[0]), str(active_function.result_type)))
                    self.in_regs = (False,)
                    self.out_regs = (False,)
                    self.out_operands = (False,)
                elif isinstance(self.operands[0], GeneralPurposeRegister):
                    if active_function.result_type.size < self.operands[0].size:
                        raise ValueError("Register {0} can not be converted to return type {1}".
                                         format(str(self.operands[0]), str(active_function.result_type)))
                    self.in_regs = (True,)
                    self.out_regs = (False,)
                    self.out_operands = (False,)
                else:
                    raise TypeError("Invalid operand type: RETURN {0} for {1} function".
                                    format(str(self.operands[0]), str(active_function.result_type)))
            elif active_function.result_type.is_floating_point:
                if isinstance(self.operands[0], XMMRegister):
                    self.in_regs = (True,)
                    self.out_regs = (False,)
                    self.out_operands = (False,)
                else:
                    raise TypeError("Invalid operand type: RETURN {0} for {1} function".
                                    format(str(self.operands[0]), str(active_function.result_type)))
            elif active_function.result_type.is_vector:
                if isinstance(self.operands[0], (MMXRegister, XMMRegister, YMMRegister)) and \
                        active_function.result_type.size == self.operands[0].size:
                    self.in_regs = (True,)
                    self.out_regs = (False,)
                    self.out_operands = (False,)
                else:
                    raise TypeError("Invalid operand type: RETURN {0} for {1} function".
                                    format(str(self.operands[0]), str(active_function.result_type)))
            else:
                raise SyntaxError("Invalid operand type: RETURN " + ", ".join(map(format_operand_type, self.operands)))
        else:
            raise SyntaxError("Pseudo-instruction \"RETURN\" requires 0 or 1 operands")
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)
Пример #11
0
    def __init__(self, *args, **kwargs):
        from peachpy.x86_64.function import active_function
        from peachpy.x86_64.registers import GeneralPurposeRegister, MMXRegister, XMMRegister, YMMRegister

        origin = kwargs.get("origin")
        prototype = kwargs.get("prototype")
        if origin is None and prototype is None and peachpy.x86_64.options.get_debug_level(
        ) > 0:
            origin = inspect.stack()
        super(RETURN, self).__init__("RETURN", origin=origin)
        self.operands = tuple(map(check_operand, args))
        if len(self.operands) == 0:
            # It is not an error to return nothing from a function with a return type
            self.in_regs = tuple()
            self.out_regs = tuple()
            self.out_operands = tuple()
        elif len(self.operands) == 1:
            # It is an error to return something from a void function
            from peachpy.util import is_int64, int_size
            if active_function.result_type is None:
                raise ValueError("Void function should not return a value")
            if active_function.result_type.is_integer or active_function.result_type.is_pointer:
                if is_int64(self.operands[0]):
                    if active_function.result_type.size < int_size(
                            self.operands[0]):
                        raise ValueError(
                            "Value {0} can not be represented with return type {1}"
                            .format(str(self.operands[0]),
                                    str(active_function.result_type)))
                    self.in_regs = (False, )
                    self.out_regs = (False, )
                    self.out_operands = (False, )
                elif isinstance(self.operands[0], GeneralPurposeRegister):
                    if active_function.result_type.size < self.operands[0].size:
                        raise ValueError(
                            "Register {0} can not be converted to return type {1}"
                            .format(str(self.operands[0]),
                                    str(active_function.result_type)))
                    self.in_regs = (True, )
                    self.out_regs = (False, )
                    self.out_operands = (False, )
                else:
                    raise TypeError(
                        "Invalid operand type: RETURN {0} for {1} function".
                        format(str(self.operands[0]),
                               str(active_function.result_type)))
            elif active_function.result_type.is_floating_point:
                if isinstance(self.operands[0], XMMRegister):
                    self.in_regs = (True, )
                    self.out_regs = (False, )
                    self.out_operands = (False, )
                else:
                    raise TypeError(
                        "Invalid operand type: RETURN {0} for {1} function".
                        format(str(self.operands[0]),
                               str(active_function.result_type)))
            elif active_function.result_type.is_vector:
                if isinstance(self.operands[0], (MMXRegister, XMMRegister, YMMRegister)) and \
                        active_function.result_type.size == self.operands[0].size:
                    self.in_regs = (True, )
                    self.out_regs = (False, )
                    self.out_operands = (False, )
                else:
                    raise TypeError(
                        "Invalid operand type: RETURN {0} for {1} function".
                        format(str(self.operands[0]),
                               str(active_function.result_type)))
            else:
                raise SyntaxError(
                    "Invalid operand type: RETURN " +
                    ", ".join(map(format_operand_type, self.operands)))
        else:
            raise SyntaxError(
                "Pseudo-instruction \"RETURN\" requires 0 or 1 operands")
        if peachpy.stream.active_stream is not None:
            peachpy.stream.active_stream.add_instruction(self)