Beispiel #1
0
    def clean(self, return_address):
        instructions = []
        instructions.append(asm.POP(asm.registers.rsp).encode())

        instructions.append(asm.MOV(asm.rax, return_address).encode())
        instructions.append(asm.JMP(asm.rax).encode())

        offset = self.data_address
        for i in instructions:
            offset = jitcompiler_instance.global_allocator.write_instruction(
                i, offset)
Beispiel #2
0
    def compile_absolute_jump(self, mfunction, block):

        stub_label = "Stub_label_jump" + str(id(block))

        old_code_offset = jitcompiler_instance.global_allocator.code_offset

        c_buffer = ffi.from_buffer(
            jitcompiler_instance.global_allocator.code_section)
        address = lib.get_address(
            c_buffer, jitcompiler_instance.global_allocator.stub_offset)

        jump_instruction = asm.MOV(asm.r10, address)
        mfunction.allocator.encode(jump_instruction)
        mfunction.allocator.encode(asm.JMP(asm.r10))

        # Now create the stub
        stub = StubBB(block, jump_instruction, old_code_offset)
        self.compile_stub(mfunction, stub)
Beispiel #3
0
    def compile_bb_stub(self,
                        mfunction,
                        true_block,
                        false_block,
                        test_instruction,
                        true_instructions=None):

        # Save both offsets
        old_stub_offset = jitcompiler_instance.global_allocator.stub_offset
        old_code_offset = jitcompiler_instance.global_allocator.code_offset

        # And update the dictionary of ids and blocks
        # Compute the offset to the stub, by adding the size of the JL instruction
        offset = old_stub_offset - old_code_offset
        peachpy_instruction = test_instruction(
            asm.operand.RIPRelativeOffset(offset - 6))

        mfunction.allocator.encode(peachpy_instruction)

        # Compile a stub for each branch
        jump_stub = StubBB(true_block, peachpy_instruction, old_code_offset)

        # If any, add some custom instructions for the true branch of the test
        jump_stub.instructions_before = true_instructions
        self.compile_stub(mfunction, jump_stub)

        # For now, jump to the newly compiled stub,
        # This code will be patched later
        old_code_offset = jitcompiler_instance.global_allocator.code_offset

        # Compute the address of the false block stub
        c_buffer = ffi.from_buffer(
            jitcompiler_instance.global_allocator.code_section)
        address_false = lib.get_address(
            c_buffer, jitcompiler_instance.global_allocator.stub_offset)

        peachpy_instruction = asm.MOV(asm.r10, address_false)
        mfunction.allocator.encode(peachpy_instruction)
        mfunction.allocator.encode(asm.JMP(asm.r10))

        # We store the MOV into the register as the jumping instruction, we just need to patch this
        notjump_stub = StubBB(false_block, peachpy_instruction,
                              old_code_offset)
        self.compile_stub(mfunction, notjump_stub)
Beispiel #4
0
    def clean(self, class_address, address_class_function):
        instructions = []

        # Now push the function address
        instructions.append(asm.MOV(asm.rax, class_address))
        instructions.append(asm.PUSH(asm.rax))

        instructions.append(asm.MOV(asm.r10, address_class_function))
        instructions.append(asm.CALL(asm.r10))

        # Clean the stack
        instructions.append(asm.ADD(asm.registers.rsp, 32))

        # Finally, jump to the correct destination
        instructions.append(asm.MOV(asm.rax, class_address))
        instructions.append(asm.MOV(asm.r11, self.return_address))
        instructions.append(asm.JMP(asm.r11))

        offset = self.data_address
        for i in instructions:
            offset = jitcompiler_instance.global_allocator.write_instruction(
                i.encode(), offset)
Beispiel #5
0
    def clean(self, return_address, function_address, canary_value=None):
        instructions = []

        # restore rsp
        instructions.append(asm.POP(asm.registers.rsp).encode())

        if canary_value in stubhandler_instance.class_stub_addresses:
            instructions.append(asm.ADD(asm.registers.rsp, 32).encode())
        else:
            # Discard the three top values on the stack
            instructions.append(asm.ADD(asm.registers.rsp, 24).encode())

        # Now push the function address
        instructions.append(asm.MOV(asm.rax, function_address).encode())
        instructions.append(asm.PUSH(asm.rax).encode())

        # Finally, jump to the correct destination
        instructions.append(asm.MOV(asm.rax, return_address).encode())
        instructions.append(asm.JMP(asm.rax).encode())

        offset = self.data_address
        for i in instructions:
            offset = jitcompiler_instance.global_allocator.write_instruction(
                i, offset)
Beispiel #6
0
    def allocate_instance(self, class_address, init_function, class_function):
        # Save the address of the initializer definition
        c_buffer = stub_handler.ffi.from_buffer(self.global_allocator.code_section)
        init_code_address = stub_handler.lib.get_address(c_buffer, self.global_allocator.code_offset)

        self.global_allocator.jitcompiler.initializer_addresses[class_function.name] = init_code_address

        instructions = list()

        # Move the next available address into rax to return it
        instructions.append(asm.MOV(asm.rax, self.register_allocation))

        # Construct the header with the size of the object
        size = 2
        instructions.append(asm.MOV(asm.operand.MemoryOperand(asm.r15), size))

        # Put a pointer to the class address in the second field
        instructions.append(asm.MOV(asm.r10, class_address))
        instructions.append(asm.MOV(asm.operand.MemoryOperand(self.register_allocation + 8), asm.r10))

        # Increment the allocation pointer
        instructions.append(asm.ADD(self.register_allocation, 8 * 5))

        # Finally, tag the address inside rax
        tag_instructions = self.global_allocator.jitcompiler.tags.tag_object_asm(asm.rax)

        instructions.extend(tag_instructions)

        # Now call the __init__() method of the class if any
        # TODO: handle __init__ with more than 1 parameters
        if init_function is not None:
            init_offset = 4

            # Save the return address of the current call
            instructions.append(asm.POP(asm.r9))

            # Saving parameter
            instructions.append(asm.POP(asm.r8))

            # Depop the class address
            instructions.append(asm.ADD(asm.registers.rsp, 8))

            # TODO: problem stack size
            instructions.append(asm.PUSH(asm.r9))

            # Push back object and parameters
            instructions.append(asm.PUSH(asm.rax))
            instructions.append(asm.PUSH(asm.r8))

            # Make the call to init
            instructions.append(asm.ADD(asm.r10, 8 * init_offset))
            instructions.append(asm.CALL(asm.operand.MemoryOperand(asm.r10)))

        # Saving return address in a register
        instructions.append(asm.POP(asm.r9))

        instructions.append(asm.JMP(asm.r9))

        offset = self.global_allocator.code_offset
        for i in instructions:
            offset = self.global_allocator.write_instruction(i.encode(), offset)

        self.global_allocator.code_offset = offset