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__
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
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
,
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
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
{
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.
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
),
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
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
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
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
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
,
106 size_t* bytes_needed
);
109 }; // namespace sidestep
111 #endif // SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__