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 : // This class hot patches a function in memory: all calls to a function will
16 : // redirected to a new function using JMP instructions.
17 : //
18 : // The function must have been prepared for hot patching: it must start with an
19 : // instruction that is at least two bytes long and must have at least 5-byte
20 : // padding before it and must have at least 2-byte alignment. The alignment
21 : // precondition is checked using the CHECK macro. The rest of the preconditions
22 : // are not checked.
23 : //
24 : // The hot patching does the following:
25 : // - Removes write protection from the pages where it needs to write.
26 : // - Writes the a PC-relative JMP instruction to the 5-byte padding before
27 : // the function. (Opcode: 0xE9 [32-bit PC-relative address])
28 : // - Overwrites the first two bytes of the function with a JMP -5 short jump
29 : // instruction. (Opcode: 0xEB 0xF9)
30 : // - Restores the old protection.
31 : //
32 : // We also DCHECK that the bytes in the padding that we overwrite are all 0xCC
33 : // bytes. These are used by the instrumenter in the paddings. These DCHECKs
34 : // need to be removed to support hot patching a function more than once.
35 :
36 : #ifndef SYZYGY_AGENT_COMMON_HOT_PATCHER_H_
37 : #define SYZYGY_AGENT_COMMON_HOT_PATCHER_H_
38 :
39 : #include <base/macros.h>
40 :
41 : namespace agent {
42 : namespace common {
43 :
44 : class HotPatcher {
45 : public:
46 : typedef void* FunctionPointer;
47 :
48 E : HotPatcher() { }
49 E : ~HotPatcher() { }
50 :
51 : // Applies hot patching to a function.
52 : // @param function_entry_point The start address of the function to be hot
53 : // patched.
54 : // @param new_entry_point A new function with the same signature that should
55 : // be called instead of the old one.
56 : // @pre The function must have been prepared for hot patching: it must start
57 : // with an instruction that is at least two bytes long and must have
58 : // at least 5-byte padding before it and must have at least 2-byte
59 : // alignment.
60 : bool Patch(FunctionPointer function_entry_point,
61 : FunctionPointer new_entry_point);
62 :
63 : private:
64 : DISALLOW_COPY_AND_ASSIGN(HotPatcher);
65 : };
66 :
67 : } // namespace common
68 : } // namespace agent
69 :
70 : #endif // SYZYGY_AGENT_COMMON_HOT_PATCHER_H_
|