blob: 8d7f8513e571dc2c2650cfef07590dce4805465a [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.
//
// This class hot patches a function in memory: all calls to a function will
// redirected to a new function using JMP instructions.
//
// The function must have been prepared for hot patching: it must start with an
// instruction that is at least two bytes long and must have at least 5-byte
// padding before it and must have at least 2-byte alignment. The alignment
// precondition is checked using the CHECK macro. The rest of the preconditions
// are not checked.
//
// The hot patching does the following:
// - Removes write protection from the pages where it needs to write.
// - Writes the a PC-relative JMP instruction to the 5-byte padding before
// the function. (Opcode: 0xE9 [32-bit PC-relative address])
// - Overwrites the first two bytes of the function with a JMP -5 short jump
// instruction. (Opcode: 0xEB 0xF9)
// - Restores the old protection.
//
// We also DCHECK that the bytes in the padding that we overwrite are all 0xCC
// bytes. These are used by the instrumenter in the paddings. These DCHECKs
// need to be removed to support hot patching a function more than once.
#ifndef SYZYGY_AGENT_COMMON_HOT_PATCHER_H_
#define SYZYGY_AGENT_COMMON_HOT_PATCHER_H_
#include <base/macros.h>
namespace agent {
namespace common {
class HotPatcher {
public:
typedef void* FunctionPointer;
HotPatcher() { }
~HotPatcher() { }
// Applies hot patching to a function.
// @param function_entry_point The start address of the function to be hot
// patched.
// @param new_entry_point A new function with the same signature that should
// be called instead of the old one.
// @pre The function must have been prepared for hot patching: it must start
// with an instruction that is at least two bytes long and must have
// at least 5-byte padding before it and must have at least 2-byte
// alignment.
bool Patch(FunctionPointer function_entry_point,
FunctionPointer new_entry_point);
private:
DISALLOW_COPY_AND_ASSIGN(HotPatcher);
};
} // namespace common
} // namespace agent
#endif // SYZYGY_AGENT_COMMON_HOT_PATCHER_H_