Esempio n. 1
0
    def encode(self, encoder, section_index_map, symbol_index_map):
        from peachpy.formats.macho.section import Section
        from peachpy.util import ilog2

        symbol = 0
        if isinstance(self.symbol, Symbol):
            # Set "external" bit (bit 27) if referencing an external symbol
            symbol = symbol_index_map[self.symbol] | 0x8000000
        elif isinstance(self.symbol, Section):
            symbol = section_index_map[self.symbol]
        if self.is_pc_relative:
            # Set "pc_relative" bit (bit 24) if the relocation is relative to the program counter
            symbol |= 0x1000000
        log2_size = ilog2(self.size)
        symbol |= log2_size << 25
        symbol |= self.type << 28

        return encoder.uint32(self.offset) + encoder.uint32(symbol)
Esempio n. 2
0
def modrm_sib_disp(reg, rm, force_sib=False, min_disp=0):
    from peachpy.x86_64.operand import MemoryAddress
    from peachpy.x86_64.registers import rsp, rbp, r12, r13
    from peachpy.util import is_int, is_sint8, ilog2

    assert is_int(reg) and 0 <= reg <= 7, \
        "Constant reg value expected, got " + str(reg)
    assert isinstance(rm, MemoryAddress)

    # TODO: support global addresses, including rip-relative addresses
    assert rm.base is not None or rm.index is not None, \
        "Global addressing is not yet supported"

    #                    ModR/M byte
    # +----------------+---------------+--------------+
    # | Bits 6-7: mode | Bits 3-5: reg | Bits 0-2: rm |
    # +----------------+---------------+--------------+
    #
    #                         SIB byte
    # +-----------------+-----------------+----------------+
    # | Bits 6-7: scale | Bits 3-5: index | Bits 0-2: base |
    # +-----------------+-----------------+----------------+
    if not force_sib and rm.index is None and rm.base.lcode != 0b100:
        # No SIB byte
        if rm.displacement == 0 and rm.base != rbp and rm.base != r13 and min_disp <= 0:
            # ModRM.mode = 0 (no displacement)

            assert rm.base.lcode != 0b100, "rsp/r12 are not encodable as a base register (interpreted as SIB indicator)"
            assert rm.base.lcode != 0b101, "rbp/r13 is not encodable as a base register (interpreted as disp32 address)"
            return bytearray([(reg << 3) | rm.base.lcode])
        elif is_sint8(rm.displacement) and min_disp <= 1:
            # ModRM.mode = 1 (8-bit displacement)

            assert rm.base.lcode != 0b100, "rsp/r12 are not encodable as a base register (interpreted as SIB indicator)"
            return bytearray(
                [0x40 | (reg << 3) | rm.base.lcode, rm.displacement & 0xFF])
        else:
            # ModRM.mode == 2 (32-bit displacement)

            assert rm.base.lcode != 0b100, "rsp/r12 are not encodable as a base register (interpreted as SIB indicator)"
            return bytearray([
                0x80 | (reg << 3) | rm.base.lcode, rm.displacement & 0xFF,
                (rm.displacement >> 8) & 0xFF, (rm.displacement >> 16) & 0xFF,
                (rm.displacement >> 24) & 0xFF
            ])
    else:
        # All encodings below use ModRM.rm = 4 (0b100) to indicate the presence of SIB

        assert rsp != rm.index, "rsp is not encodable as an index register (interpreted as no index)"
        # Index = 4 (0b100) denotes no-index encoding
        index = 0x4 if rm.index is None else rm.index.lcode
        scale = 0 if rm.scale is None else ilog2(rm.scale)
        if rm.base is None:
            # SIB.base = 5 (0b101) and ModRM.mode = 0 indicates no-base encoding with disp32

            return bytearray([(reg << 3) | 0x4,
                              (scale << 6) | (index << 3) | 0x5,
                              rm.displacement & 0xFF,
                              (rm.displacement >> 8) & 0xFF,
                              (rm.displacement >> 16) & 0xFF,
                              (rm.displacement >> 24) & 0xFF])
        else:
            if rm.displacement == 0 and rm.base.lcode != 0b101 and min_disp <= 0:
                # ModRM.mode == 0 (no displacement)

                assert rm.base.lcode != 0b101, \
                    "rbp/r13 is not encodable as a base register (interpreted as disp32 address)"
                return bytearray([(reg << 3) | 0x4,
                                  (scale << 6) | (index << 3) | rm.base.lcode])
            elif is_sint8(rm.displacement) and min_disp <= 1:
                # ModRM.mode == 1 (8-bit displacement)

                return bytearray([(reg << 3) | 0x44,
                                  (scale << 6) | (index << 3) | rm.base.lcode,
                                  rm.displacement & 0xFF])
            else:
                # ModRM.mode == 2 (32-bit displacement)

                return bytearray([(reg << 3) | 0x84,
                                  (scale << 6) | (index << 3) | rm.base.lcode,
                                  rm.displacement & 0xFF,
                                  (rm.displacement >> 8) & 0xFF,
                                  (rm.displacement >> 16) & 0xFF,
                                  (rm.displacement >> 24) & 0xFF])
Esempio n. 3
0
 def log2_alignment(self):
     from peachpy.util import ilog2
     return ilog2(self._alignment)
Esempio n. 4
0
def modrm_sib_disp(reg, rm, force_sib=False, min_disp=0, disp8xN=None):
    from peachpy.x86_64.operand import MemoryAddress
    from peachpy.x86_64.registers import rsp, rbp, r12, r13
    from peachpy.util import is_int, is_sint8, ilog2

    assert is_int(reg) and 0 <= reg <= 7, \
        "Constant reg value expected, got " + str(reg)
    assert isinstance(rm, (MemoryAddress, int))

    if disp8xN is None:
        disp8xN = 1
    assert disp8xN in [1, 2, 4, 8, 16, 32, 64]

    #                    ModR/M byte
    # +----------------+---------------+--------------+
    # | Bits 6-7: mode | Bits 3-5: reg | Bits 0-2: rm |
    # +----------------+---------------+--------------+
    #
    #                         SIB byte
    # +-----------------+-----------------+----------------+
    # | Bits 6-7: scale | Bits 3-5: index | Bits 0-2: base |
    # +-----------------+-----------------+----------------+
    if isinstance(rm, MemoryAddress):
        # TODO: support global addresses, including rip-relative addresses
        assert rm.base is not None or rm.index is not None, \
            "Global addressing is not yet supported"
        if not force_sib and rm.index is None and rm.base.lcode != 0b100:
            # No SIB byte
            if rm.displacement == 0 and rm.base != rbp and rm.base != r13 and min_disp <= 0:
                # ModRM.mode = 0 (no displacement)

                assert rm.base.lcode != 0b100, \
                    "rsp/r12 are not encodable as a base register (interpreted as SIB indicator)"
                assert rm.base.lcode != 0b101, \
                    "rbp/r13 is not encodable as a base register (interpreted as disp32 address)"
                return bytearray([(reg << 3) | rm.base.lcode])
            elif (rm.displacement % disp8xN == 0) and is_sint8(rm.displacement // disp8xN) and min_disp <= 1:
                # ModRM.mode = 1 (8-bit displacement)

                assert rm.base.lcode != 0b100, \
                    "rsp/r12 are not encodable as a base register (interpreted as SIB indicator)"
                return bytearray([0x40 | (reg << 3) | rm.base.lcode, (rm.displacement // disp8xN) & 0xFF])
            else:
                # ModRM.mode == 2 (32-bit displacement)

                assert rm.base.lcode != 0b100, \
                    "rsp/r12 are not encodable as a base register (interpreted as SIB indicator)"
                return bytearray([0x80 | (reg << 3) | rm.base.lcode,
                                 rm.displacement & 0xFF, (rm.displacement >> 8) & 0xFF,
                                 (rm.displacement >> 16) & 0xFF, (rm.displacement >> 24) & 0xFF])
        else:
            # All encodings below use ModRM.rm = 4 (0b100) to indicate the presence of SIB

            assert rsp != rm.index, "rsp is not encodable as an index register (interpreted as no index)"
            # Index = 4 (0b100) denotes no-index encoding
            index = 0x4 if rm.index is None else rm.index.lcode
            scale = 0 if rm.scale is None else ilog2(rm.scale)
            if rm.base is None:
                # SIB.base = 5 (0b101) and ModRM.mode = 0 indicates no-base encoding with disp32

                return bytearray([(reg << 3) | 0x4, (scale << 6) | (index << 3) | 0x5,
                                 rm.displacement & 0xFF, (rm.displacement >> 8) & 0xFF,
                                 (rm.displacement >> 16) & 0xFF, (rm.displacement >> 24) & 0xFF])
            else:
                if rm.displacement == 0 and rm.base.lcode != 0b101 and min_disp <= 0:
                    # ModRM.mode == 0 (no displacement)

                    assert rm.base.lcode != 0b101, \
                        "rbp/r13 is not encodable as a base register (interpreted as disp32 address)"
                    return bytearray([(reg << 3) | 0x4, (scale << 6) | (index << 3) | rm.base.lcode])
                elif (rm.displacement % disp8xN == 0) and is_sint8(rm.displacement // disp8xN) and min_disp <= 1:
                    # ModRM.mode == 1 (8-bit displacement)

                    return bytearray([(reg << 3) | 0x44, (scale << 6) | (index << 3) | rm.base.lcode,
                                      (rm.displacement // disp8xN) & 0xFF])
                else:
                    # ModRM.mode == 2 (32-bit displacement)

                    return bytearray([(reg << 3) | 0x84, (scale << 6) | (index << 3) | rm.base.lcode,
                                     rm.displacement & 0xFF, (rm.displacement >> 8) & 0xFF,
                                     (rm.displacement >> 16) & 0xFF, (rm.displacement >> 24) & 0xFF])
    else:
        # ModRM.mode == 0 and ModeRM.rm == 5 (0b101) indicates (rip + disp32) addressing
        return bytearray([0b00000101 | (reg << 3), rm & 0xFF, (rm >> 8) & 0xFF, (rm >> 16) & 0xFF, (rm >> 24) & 0xFF])
Esempio n. 5
0
 def log2_alignment(self):
     from peachpy.util import ilog2
     return ilog2(self._alignment)