Roll src/third_party/WebKit e0eac24:489c548 (svn 193311:193320)
[chromium-blink-merge.git] / sandbox / win / src / sidestep / preamble_patcher.h
blob3a0985ce9fa0cb88f705f61027db6d645866e1fc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Definition of PreamblePatcher
7 #ifndef SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__
8 #define SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__
10 #include <stddef.h>
12 namespace sidestep {
14 // Maximum size of the preamble stub. We overwrite at least the first 5
15 // bytes of the function. Considering the worst case scenario, we need 4
16 // bytes + the max instruction size + 5 more bytes for our jump back to
17 // the original code. With that in mind, 32 is a good number :)
18 const size_t kMaxPreambleStubSize = 32;
20 // Possible results of patching/unpatching
21 enum SideStepError {
22 SIDESTEP_SUCCESS = 0,
23 SIDESTEP_INVALID_PARAMETER,
24 SIDESTEP_INSUFFICIENT_BUFFER,
25 SIDESTEP_JUMP_INSTRUCTION,
26 SIDESTEP_FUNCTION_TOO_SMALL,
27 SIDESTEP_UNSUPPORTED_INSTRUCTION,
28 SIDESTEP_NO_SUCH_MODULE,
29 SIDESTEP_NO_SUCH_FUNCTION,
30 SIDESTEP_ACCESS_DENIED,
31 SIDESTEP_UNEXPECTED,
34 // Implements a patching mechanism that overwrites the first few bytes of
35 // a function preamble with a jump to our hook function, which is then
36 // able to call the original function via a specially-made preamble-stub
37 // that imitates the action of the original preamble.
39 // Note that there are a number of ways that this method of patching can
40 // fail. The most common are:
41 // - If there is a jump (jxx) instruction in the first 5 bytes of
42 // the function being patched, we cannot patch it because in the
43 // current implementation we do not know how to rewrite relative
44 // jumps after relocating them to the preamble-stub. Note that
45 // if you really really need to patch a function like this, it
46 // would be possible to add this functionality (but at some cost).
47 // - If there is a return (ret) instruction in the first 5 bytes
48 // we cannot patch the function because it may not be long enough
49 // for the jmp instruction we use to inject our patch.
50 // - If there is another thread currently executing within the bytes
51 // that are copied to the preamble stub, it will crash in an undefined
52 // way.
54 // If you get any other error than the above, you're either pointing the
55 // patcher at an invalid instruction (e.g. into the middle of a multi-
56 // byte instruction, or not at memory containing executable instructions)
57 // or, there may be a bug in the disassembler we use to find
58 // instruction boundaries.
59 class PreamblePatcher {
60 public:
61 // Patches target_function to point to replacement_function using a provided
62 // preamble_stub of stub_size bytes.
63 // Returns An error code indicating the result of patching.
64 template <class T>
65 static SideStepError Patch(T target_function, T replacement_function,
66 void* preamble_stub, size_t stub_size) {
67 return RawPatchWithStub(target_function, replacement_function,
68 reinterpret_cast<unsigned char*>(preamble_stub),
69 stub_size, NULL);
72 private:
74 // Patches a function by overwriting its first few bytes with
75 // a jump to a different function. This is similar to the RawPatch
76 // function except that it uses the stub allocated by the caller
77 // instead of allocating it.
79 // To use this function, you first have to call VirtualProtect to make the
80 // target function writable at least for the duration of the call.
82 // target_function: A pointer to the function that should be
83 // patched.
85 // replacement_function: A pointer to the function that should
86 // replace the target function. The replacement function must have
87 // exactly the same calling convention and parameters as the original
88 // function.
90 // preamble_stub: A pointer to a buffer where the preamble stub
91 // should be copied. The size of the buffer should be sufficient to
92 // hold the preamble bytes.
94 // stub_size: Size in bytes of the buffer allocated for the
95 // preamble_stub
97 // bytes_needed: Pointer to a variable that receives the minimum
98 // number of bytes required for the stub. Can be set to NULL if you're
99 // not interested.
101 // Returns An error code indicating the result of patching.
102 static SideStepError RawPatchWithStub(void* target_function,
103 void *replacement_function,
104 unsigned char* preamble_stub,
105 size_t stub_size,
106 size_t* bytes_needed);
109 }; // namespace sidestep
111 #endif // SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__