1 : // Copyright 2015 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // A basic block subgraph transform that prepares a block for hot patching.
16 : //
17 : // To make a block hot patchable, we insert five bytes of padding before the
18 : // block to accommodate a long jump instruction and make the first instruction
19 : // of the block atomically replaceable with a two-byte jump that jumps
20 : // to the long jump in the padding. An instruction is atomically replaceable
21 : // if it is at least two bytes long and its first two bytes do not cross
22 : // a 4-byte boundary. Therefore the alignment of the block will be increased
23 : // to at least two and if the block begins with a one-byte instruction, a
24 : // two-byte NOP will be prepended and the references referring after the NOP
25 : // will refer to the beginning of the block.
26 :
27 : #ifndef SYZYGY_PE_TRANSFORMS_PE_HOT_PATCHING_BASIC_BLOCK_TRANSFORM_H_
28 : #define SYZYGY_PE_TRANSFORMS_PE_HOT_PATCHING_BASIC_BLOCK_TRANSFORM_H_
29 :
30 : #include <vector>
31 :
32 : #include "syzygy/block_graph/transforms/iterative_transform.h"
33 :
34 : namespace pe {
35 : namespace transforms {
36 :
37 : class PEHotPatchingBasicBlockTransform
38 : : public block_graph::transforms::NamedBasicBlockSubGraphTransformImpl<
39 : PEHotPatchingBasicBlockTransform> {
40 : public:
41 : typedef block_graph::BlockGraph BlockGraph;
42 : typedef block_graph::BasicBlockSubGraph BasicBlockSubGraph;
43 : typedef block_graph::TransformPolicyInterface TransformPolicyInterface;
44 : typedef BasicBlockSubGraph::BasicCodeBlock BasicCodeBlock;
45 :
46 : // The transform name.
47 : static const char kTransformName[];
48 :
49 E : PEHotPatchingBasicBlockTransform() {}
50 :
51 : // BasicBlockSubGraphTransformInterface implementation.
52 : // @pre The subgraph must contain a single block that must begin with
53 : // a basic code block.
54 : virtual bool TransformBasicBlockSubGraph(
55 : const TransformPolicyInterface* policy,
56 : BlockGraph* block_graph,
57 : BasicBlockSubGraph* bbsg) override;
58 :
59 : protected:
60 : // The length of a long jump instruction. This is the amount of padding that
61 : // will be inserted before each block that needs hot patching.
62 : static const size_t kLongJumpInstructionLength;
63 :
64 : // Insert a NOP at the beginning of the code block.
65 : // @param code_block The basic code block to insert into.
66 : void InsertTwoByteNopAtBlockBeginning(BasicCodeBlock* code_block);
67 :
68 : // Checks if the first instruction of a basic code block is atomically
69 : // replaceable.
70 : // @param code_block The basic code block to examine.
71 : // @returns true iff the first instruction of the basic code block is
72 : // atomically replaceable.
73 : bool IsAtomicallyReplaceableFirstInstruction(BasicCodeBlock* code_block);
74 :
75 : // Ensures that the first instruction of a block is atomically replaceable.
76 : // This function increases the alignment to 2 (if it was lower), checks
77 : // the first instruction, and if it is not atomically replaceable
78 : // (only one byte long) then prepends a two-byte NOP to the first basic code
79 : // block.
80 : // @param bbsg The basic block subgraph to change.
81 : // @pre The subgraph must contain a single block that must begin with
82 : // a basic code block.
83 : void EnsureAtomicallyReplaceableFirstInstruction(BasicBlockSubGraph* bbsg);
84 :
85 : // Ensures that there is at least kLongJumpInstructionLength padding before
86 : // the block represented by the basic block subgraph.
87 : // @param block The target block.
88 : // @pre The subgraph must contain a single block.
89 : void EnsurePaddingForJumpBeforeBlock(BasicBlockSubGraph* bbsg);
90 :
91 : // Gets the first basic code block of a block in a subgraph according to
92 : // the basic block ordering in the block description.
93 : // @param bbsg The basic block subgraph to query.
94 : // @returns The first code block
95 : // @pre The subgraph must contain a single block that must begin with
96 : // a basic code block.
97 : BasicCodeBlock* GetFirstBasicCodeBlock(BasicBlockSubGraph* bbsg);
98 :
99 : private:
100 : DISALLOW_COPY_AND_ASSIGN(PEHotPatchingBasicBlockTransform);
101 : };
102 :
103 : } // namespace transforms
104 : } // namespace pe
105 :
106 : #endif // SYZYGY_PE_TRANSFORMS_PE_HOT_PATCHING_BASIC_BLOCK_TRANSFORM_H_
|