blob: a2c99a9a73b0b1ab0f7f80b48337a2479babe7d5 [file] [log] [blame]
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// The HotPatchingWriter allocates executable memory pages and writes blocks
// into this memory area, where they can be executed.
//
// First the |Init| function must be called. This allocates a new executable
// virtual memory of a given size using VirtualAlloc.
//
// The |Write| function can be used to write a block into this memory area.
// It does the following:
// - Copies the block data into the executable virtual memory.
// - Changes the data of the block to point into the new location (the block
// will not own the data)
// - Finalizes the bytes of inter-block references in the block data.
//
// NOTE: To write a block with this class, the |data| of all referred blocks
// must be backed by executable memory: they must be either blocks
// decomposed by the hot patching decomposer or blocks already written by
// the writer. The reason for this restriction is because the references
// will be calculated using the |data| pointers of the blocks.
// TODO(cseri): The precondition is currently not checked. We could introduce
// a new flag for in-memory executable blocks.
//
// TODO(cseri): Implement some page protection logic, the write permission
// should be removed after the writes are finished.
// TODO(cseri): Consider freeing the allocated virtual memory in destructor.
#ifndef SYZYGY_PE_HOT_PATCHING_WRITER_H_
#define SYZYGY_PE_HOT_PATCHING_WRITER_H_
#include "syzygy/block_graph/block_graph.h"
namespace pe {
class HotPatchingWriter {
public:
typedef block_graph::BlockGraph BlockGraph;
typedef void* FunctionPointer;
HotPatchingWriter();
~HotPatchingWriter();
// Queries how much of the virtual memory of the writer has used so far.
// @returns the size of the written code, in bytes.
size_t GetUsedMemory() const;
// Allocates an executable virtual page with a given size that will be used to
// write the code into.
// @param virtual_memory_size The size of the requested virtual memory, in
// bytes.
bool Init(size_t virtual_memory_size);
// Writes a block into the executable memory.
// @param block The block to write.
// @returns A pointer to the written function on success, nullptr if there was
// not enough space to write the function.
// @pre |Init| must be called before a call to this function.
FunctionPointer Write(BlockGraph::Block* block);
// Returns the size of the allocated virtual memory. Valid after the |Init|
// function is called.
// @returns the size of the virtual memory, in bytes.
size_t virtual_memory_size() const {
return virtual_memory_size_;
}
protected:
// The pointer to the virtual memory.
LPVOID virtual_memory_;
// The size of the allocated virtual memory. Valid after the |Init| function
// is called.
size_t virtual_memory_size_;
// The pointer to the current position in the virtual memory.
uint8_t* virtual_memory_cursor_;
private:
DISALLOW_COPY_AND_ASSIGN(HotPatchingWriter);
};
} // namespace pe
#endif // SYZYGY_PE_HOT_PATCHING_WRITER_H_