preamble_patcher.h 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
  2. /* Copyright (c) 2007, Google Inc.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above
  12. * copyright notice, this list of conditions and the following disclaimer
  13. * in the documentation and/or other materials provided with the
  14. * distribution.
  15. * * Neither the name of Google Inc. nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. * ---
  32. * Author: Joi Sigurdsson
  33. * Author: Scott Francis
  34. *
  35. * Definition of PreamblePatcher
  36. */
  37. #ifndef GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_
  38. #define GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_
  39. #include "config.h"
  40. #include <windows.h>
  41. // compatibility shim
  42. #include "base/logging.h"
  43. #define SIDESTEP_ASSERT(cond) RAW_DCHECK(cond, #cond)
  44. #define SIDESTEP_LOG(msg) RAW_VLOG(1, msg)
  45. // Maximum size of the preamble stub. We overwrite at least the first 5
  46. // bytes of the function. Considering the worst case scenario, we need 4
  47. // bytes + the max instruction size + 5 more bytes for our jump back to
  48. // the original code. With that in mind, 32 is a good number :)
  49. #ifdef _M_X64
  50. // In 64-bit mode we may need more room. In 64-bit mode all jumps must be
  51. // within +/-2GB of RIP. Because of this limitation we may need to use a
  52. // trampoline to jump to the replacement function if it is further than 2GB
  53. // away from the target. The trampoline is 14 bytes.
  54. //
  55. // So 4 bytes + max instruction size (17 bytes) + 5 bytes to jump back to the
  56. // original code + trampoline size. 64 bytes is a nice number :-)
  57. #define MAX_PREAMBLE_STUB_SIZE (64)
  58. #else
  59. #define MAX_PREAMBLE_STUB_SIZE (32)
  60. #endif
  61. // Determines if this is a 64-bit binary.
  62. #ifdef _M_X64
  63. static const bool kIs64BitBinary = true;
  64. #else
  65. static const bool kIs64BitBinary = false;
  66. #endif
  67. namespace sidestep {
  68. // Possible results of patching/unpatching
  69. enum SideStepError {
  70. SIDESTEP_SUCCESS = 0,
  71. SIDESTEP_INVALID_PARAMETER,
  72. SIDESTEP_INSUFFICIENT_BUFFER,
  73. SIDESTEP_JUMP_INSTRUCTION,
  74. SIDESTEP_FUNCTION_TOO_SMALL,
  75. SIDESTEP_UNSUPPORTED_INSTRUCTION,
  76. SIDESTEP_NO_SUCH_MODULE,
  77. SIDESTEP_NO_SUCH_FUNCTION,
  78. SIDESTEP_ACCESS_DENIED,
  79. SIDESTEP_UNEXPECTED,
  80. };
  81. #define SIDESTEP_TO_HRESULT(error) \
  82. MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, error)
  83. class DeleteUnsignedCharArray;
  84. // Implements a patching mechanism that overwrites the first few bytes of
  85. // a function preamble with a jump to our hook function, which is then
  86. // able to call the original function via a specially-made preamble-stub
  87. // that imitates the action of the original preamble.
  88. //
  89. // NOTE: This patching mechanism should currently only be used for
  90. // non-production code, e.g. unit tests, because it is not threadsafe.
  91. // See the TODO in preamble_patcher_with_stub.cc for instructions on what
  92. // we need to do before using it in production code; it's fairly simple
  93. // but unnecessary for now since we only intend to use it in unit tests.
  94. //
  95. // To patch a function, use either of the typesafe Patch() methods. You
  96. // can unpatch a function using Unpatch().
  97. //
  98. // Typical usage goes something like this:
  99. // @code
  100. // typedef int (*MyTypesafeFuncPtr)(int x);
  101. // MyTypesafeFuncPtr original_func_stub;
  102. // int MyTypesafeFunc(int x) { return x + 1; }
  103. // int HookMyTypesafeFunc(int x) { return 1 + original_func_stub(x); }
  104. //
  105. // void MyPatchInitializingFunction() {
  106. // original_func_stub = PreamblePatcher::Patch(
  107. // MyTypesafeFunc, HookMyTypesafeFunc);
  108. // if (!original_func_stub) {
  109. // // ... error handling ...
  110. // }
  111. //
  112. // // ... continue - you have patched the function successfully ...
  113. // }
  114. // @endcode
  115. //
  116. // Note that there are a number of ways that this method of patching can
  117. // fail. The most common are:
  118. // - If there is a jump (jxx) instruction in the first 5 bytes of
  119. // the function being patched, we cannot patch it because in the
  120. // current implementation we do not know how to rewrite relative
  121. // jumps after relocating them to the preamble-stub. Note that
  122. // if you really really need to patch a function like this, it
  123. // would be possible to add this functionality (but at some cost).
  124. // - If there is a return (ret) instruction in the first 5 bytes
  125. // we cannot patch the function because it may not be long enough
  126. // for the jmp instruction we use to inject our patch.
  127. // - If there is another thread currently executing within the bytes
  128. // that are copied to the preamble stub, it will crash in an undefined
  129. // way.
  130. //
  131. // If you get any other error than the above, you're either pointing the
  132. // patcher at an invalid instruction (e.g. into the middle of a multi-
  133. // byte instruction, or not at memory containing executable instructions)
  134. // or, there may be a bug in the disassembler we use to find
  135. // instruction boundaries.
  136. //
  137. // NOTE: In optimized builds, when you have very trivial functions that
  138. // the compiler can reason do not have side effects, the compiler may
  139. // reuse the result of calling the function with a given parameter, which
  140. // may mean if you patch the function in between your patch will never get
  141. // invoked. See preamble_patcher_test.cc for an example.
  142. class PERFTOOLS_DLL_DECL PreamblePatcher {
  143. public:
  144. // This is a typesafe version of RawPatch(), identical in all other
  145. // ways than it takes a template parameter indicating the type of the
  146. // function being patched.
  147. //
  148. // @param T The type of the function you are patching. Usually
  149. // you will establish this type using a typedef, as in the following
  150. // example:
  151. // @code
  152. // typedef BOOL (WINAPI *MessageBoxPtr)(HWND, LPCTSTR, LPCTSTR, UINT);
  153. // MessageBoxPtr original = NULL;
  154. // PreamblePatcher::Patch(MessageBox, Hook_MessageBox, &original);
  155. // @endcode
  156. template <class T>
  157. static SideStepError Patch(T target_function,
  158. T replacement_function,
  159. T* original_function_stub) {
  160. // NOTE: casting from a function to a pointer is contra the C++
  161. // spec. It's not safe on IA64, but is on i386. We use
  162. // a C-style cast here to emphasize this is not legal C++.
  163. return RawPatch((void*)(target_function),
  164. (void*)(replacement_function),
  165. (void**)(original_function_stub));
  166. }
  167. // Patches a named function imported from the named module using
  168. // preamble patching. Uses RawPatch() to do the actual patching
  169. // work.
  170. //
  171. // @param T The type of the function you are patching. Must
  172. // exactly match the function you specify using module_name and
  173. // function_name.
  174. //
  175. // @param module_name The name of the module from which the function
  176. // is being imported. Note that the patch will fail if this module
  177. // has not already been loaded into the current process.
  178. //
  179. // @param function_name The name of the function you wish to patch.
  180. //
  181. // @param replacement_function Your replacement function which
  182. // will be called whenever code tries to call the original function.
  183. //
  184. // @param original_function_stub Pointer to memory that should receive a
  185. // pointer that can be used (e.g. in the replacement function) to call the
  186. // original function, or NULL to indicate failure.
  187. //
  188. // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
  189. // indicates success.
  190. template <class T>
  191. static SideStepError Patch(LPCTSTR module_name,
  192. LPCSTR function_name,
  193. T replacement_function,
  194. T* original_function_stub) {
  195. SIDESTEP_ASSERT(module_name && function_name);
  196. if (!module_name || !function_name) {
  197. SIDESTEP_ASSERT(false &&
  198. "You must specify a module name and function name.");
  199. return SIDESTEP_INVALID_PARAMETER;
  200. }
  201. HMODULE module = ::GetModuleHandle(module_name);
  202. SIDESTEP_ASSERT(module != NULL);
  203. if (!module) {
  204. SIDESTEP_ASSERT(false && "Invalid module name.");
  205. return SIDESTEP_NO_SUCH_MODULE;
  206. }
  207. FARPROC existing_function = ::GetProcAddress(module, function_name);
  208. if (!existing_function) {
  209. SIDESTEP_ASSERT(
  210. false && "Did not find any function with that name in the module.");
  211. return SIDESTEP_NO_SUCH_FUNCTION;
  212. }
  213. // NOTE: casting from a function to a pointer is contra the C++
  214. // spec. It's not safe on IA64, but is on i386. We use
  215. // a C-style cast here to emphasize this is not legal C++.
  216. return RawPatch((void*)existing_function, (void*)replacement_function,
  217. (void**)(original_function_stub));
  218. }
  219. // Patches a function by overwriting its first few bytes with
  220. // a jump to a different function. This is the "worker" function
  221. // for each of the typesafe Patch() functions. In most cases,
  222. // it is preferable to use the Patch() functions rather than
  223. // this one as they do more checking at compile time.
  224. //
  225. // @param target_function A pointer to the function that should be
  226. // patched.
  227. //
  228. // @param replacement_function A pointer to the function that should
  229. // replace the target function. The replacement function must have
  230. // exactly the same calling convention and parameters as the original
  231. // function.
  232. //
  233. // @param original_function_stub Pointer to memory that should receive a
  234. // pointer that can be used (e.g. in the replacement function) to call the
  235. // original function, or NULL to indicate failure.
  236. //
  237. // @param original_function_stub Pointer to memory that should receive a
  238. // pointer that can be used (e.g. in the replacement function) to call the
  239. // original function, or NULL to indicate failure.
  240. //
  241. // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
  242. // indicates success.
  243. //
  244. // @note The preamble-stub (the memory pointed to by
  245. // *original_function_stub) is allocated on the heap, and (in
  246. // production binaries) never destroyed, resulting in a memory leak. This
  247. // will be the case until we implement safe unpatching of a method.
  248. // However, it is quite difficult to unpatch a method (because other
  249. // threads in the process may be using it) so we are leaving it for now.
  250. // See however UnsafeUnpatch, which can be used for binaries where you
  251. // know only one thread is running, e.g. unit tests.
  252. static SideStepError RawPatch(void* target_function,
  253. void* replacement_function,
  254. void** original_function_stub);
  255. // Unpatches target_function and deletes the stub that previously could be
  256. // used to call the original version of the function.
  257. //
  258. // DELETES the stub that is passed to the function.
  259. //
  260. // @param target_function Pointer to the target function which was
  261. // previously patched, i.e. a pointer which value should match the value
  262. // of the symbol prior to patching it.
  263. //
  264. // @param replacement_function Pointer to the function target_function
  265. // was patched to.
  266. //
  267. // @param original_function_stub Pointer to the stub returned when
  268. // patching, that could be used to call the original version of the
  269. // patched function. This function will also delete the stub, which after
  270. // unpatching is useless.
  271. //
  272. // If your original call was
  273. // Patch(VirtualAlloc, MyVirtualAlloc, &origptr)
  274. // then to undo it you would call
  275. // Unpatch(VirtualAlloc, MyVirtualAlloc, origptr);
  276. //
  277. // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
  278. // indicates success.
  279. static SideStepError Unpatch(void* target_function,
  280. void* replacement_function,
  281. void* original_function_stub);
  282. // A helper routine when patching, which follows jmp instructions at
  283. // function addresses, to get to the "actual" function contents.
  284. // This allows us to identify two functions that are at different
  285. // addresses but actually resolve to the same code.
  286. //
  287. // @param target_function Pointer to a function.
  288. //
  289. // @return Either target_function (the input parameter), or if
  290. // target_function's body consists entirely of a JMP instruction,
  291. // the address it JMPs to (or more precisely, the address at the end
  292. // of a chain of JMPs).
  293. template <class T>
  294. static T ResolveTarget(T target_function) {
  295. return (T)ResolveTargetImpl((unsigned char*)target_function, NULL);
  296. }
  297. // Allocates a block of memory of size MAX_PREAMBLE_STUB_SIZE that is as
  298. // close (within 2GB) as possible to target. This is done to ensure that
  299. // we can perform a relative jump from target to a trampoline if the
  300. // replacement function is > +-2GB from target. This means that we only need
  301. // to patch 5 bytes in the target function.
  302. //
  303. // @param target Pointer to target function.
  304. //
  305. // @return Returns a block of memory of size MAX_PREAMBLE_STUB_SIZE that can
  306. // be used to store a function preamble block.
  307. static unsigned char* AllocPreambleBlockNear(void* target);
  308. // Frees a block allocated by AllocPreambleBlockNear.
  309. //
  310. // @param block Block that was returned by AllocPreambleBlockNear.
  311. static void FreePreambleBlock(unsigned char* block);
  312. private:
  313. friend class DeleteUnsignedCharArray;
  314. // Used to store data allocated for preamble stubs
  315. struct PreamblePage {
  316. unsigned int magic_;
  317. PreamblePage* next_;
  318. // This member points to a linked list of free blocks within the page
  319. // or NULL if at the end
  320. void* free_;
  321. };
  322. // In 64-bit mode, the replacement function must be within 2GB of the original
  323. // target in order to only require 5 bytes for the function patch. To meet
  324. // this requirement we're creating an allocator within this class to
  325. // allocate blocks that are within 2GB of a given target. This member is the
  326. // head of a linked list of pages used to allocate blocks that are within
  327. // 2GB of the target.
  328. static PreamblePage* preamble_pages_;
  329. // Page granularity
  330. static long granularity_;
  331. // Page size
  332. static long pagesize_;
  333. // Determines if the patcher has been initialized.
  334. static bool initialized_;
  335. // Used to initialize static members.
  336. static void Initialize();
  337. // Patches a function by overwriting its first few bytes with
  338. // a jump to a different function. This is similar to the RawPatch
  339. // function except that it uses the stub allocated by the caller
  340. // instead of allocating it.
  341. //
  342. // We call VirtualProtect to make the
  343. // target function writable at least for the duration of the call.
  344. //
  345. // @param target_function A pointer to the function that should be
  346. // patched.
  347. //
  348. // @param replacement_function A pointer to the function that should
  349. // replace the target function. The replacement function must have
  350. // exactly the same calling convention and parameters as the original
  351. // function.
  352. //
  353. // @param preamble_stub A pointer to a buffer where the preamble stub
  354. // should be copied. The size of the buffer should be sufficient to
  355. // hold the preamble bytes.
  356. //
  357. // @param stub_size Size in bytes of the buffer allocated for the
  358. // preamble_stub
  359. //
  360. // @param bytes_needed Pointer to a variable that receives the minimum
  361. // number of bytes required for the stub. Can be set to NULL if you're
  362. // not interested.
  363. //
  364. // @return An error code indicating the result of patching.
  365. static SideStepError RawPatchWithStubAndProtections(
  366. void* target_function,
  367. void* replacement_function,
  368. unsigned char* preamble_stub,
  369. unsigned long stub_size,
  370. unsigned long* bytes_needed);
  371. // A helper function used by RawPatchWithStubAndProtections -- it
  372. // does everything but the VirtualProtect work. Defined in
  373. // preamble_patcher_with_stub.cc.
  374. //
  375. // @param target_function A pointer to the function that should be
  376. // patched.
  377. //
  378. // @param replacement_function A pointer to the function that should
  379. // replace the target function. The replacement function must have
  380. // exactly the same calling convention and parameters as the original
  381. // function.
  382. //
  383. // @param preamble_stub A pointer to a buffer where the preamble stub
  384. // should be copied. The size of the buffer should be sufficient to
  385. // hold the preamble bytes.
  386. //
  387. // @param stub_size Size in bytes of the buffer allocated for the
  388. // preamble_stub
  389. //
  390. // @param bytes_needed Pointer to a variable that receives the minimum
  391. // number of bytes required for the stub. Can be set to NULL if you're
  392. // not interested.
  393. //
  394. // @return An error code indicating the result of patching.
  395. static SideStepError RawPatchWithStub(void* target_function,
  396. void* replacement_function,
  397. unsigned char* preamble_stub,
  398. unsigned long stub_size,
  399. unsigned long* bytes_needed);
  400. // A helper routine when patching, which follows jmp instructions at
  401. // function addresses, to get to the "actual" function contents.
  402. // This allows us to identify two functions that are at different
  403. // addresses but actually resolve to the same code.
  404. //
  405. // @param target_function Pointer to a function.
  406. //
  407. // @param stop_before If, when following JMP instructions from
  408. // target_function, we get to the address stop, we return
  409. // immediately, the address that jumps to stop_before.
  410. //
  411. // @param stop_before_trampoline When following JMP instructions from
  412. // target_function, stop before a trampoline is detected. See comment in
  413. // PreamblePatcher::RawPatchWithStub for more information. This parameter
  414. // has no effect in 32-bit mode.
  415. //
  416. // @return Either target_function (the input parameter), or if
  417. // target_function's body consists entirely of a JMP instruction,
  418. // the address it JMPs to (or more precisely, the address at the end
  419. // of a chain of JMPs).
  420. static void* ResolveTargetImpl(unsigned char* target_function,
  421. unsigned char* stop_before,
  422. bool stop_before_trampoline = false);
  423. // Helper routine that attempts to allocate a page as close (within 2GB)
  424. // as possible to target.
  425. //
  426. // @param target Pointer to target function.
  427. //
  428. // @return Returns an address that is within 2GB of target.
  429. static void* AllocPageNear(void* target);
  430. // Helper routine that determines if a target instruction is a short
  431. // conditional jump.
  432. //
  433. // @param target Pointer to instruction.
  434. //
  435. // @param instruction_size Size of the instruction in bytes.
  436. //
  437. // @return Returns true if the instruction is a short conditional jump.
  438. static bool IsShortConditionalJump(unsigned char* target,
  439. unsigned int instruction_size);
  440. static bool IsShortJump(unsigned char *target, unsigned int instruction_size);
  441. // Helper routine that determines if a target instruction is a near
  442. // conditional jump.
  443. //
  444. // @param target Pointer to instruction.
  445. //
  446. // @param instruction_size Size of the instruction in bytes.
  447. //
  448. // @return Returns true if the instruction is a near conditional jump.
  449. static bool IsNearConditionalJump(unsigned char* target,
  450. unsigned int instruction_size);
  451. // Helper routine that determines if a target instruction is a near
  452. // relative jump.
  453. //
  454. // @param target Pointer to instruction.
  455. //
  456. // @param instruction_size Size of the instruction in bytes.
  457. //
  458. // @return Returns true if the instruction is a near absolute jump.
  459. static bool IsNearRelativeJump(unsigned char* target,
  460. unsigned int instruction_size);
  461. // Helper routine that determines if a target instruction is a near
  462. // absolute call.
  463. //
  464. // @param target Pointer to instruction.
  465. //
  466. // @param instruction_size Size of the instruction in bytes.
  467. //
  468. // @return Returns true if the instruction is a near absolute call.
  469. static bool IsNearAbsoluteCall(unsigned char* target,
  470. unsigned int instruction_size);
  471. // Helper routine that determines if a target instruction is a near
  472. // absolute call.
  473. //
  474. // @param target Pointer to instruction.
  475. //
  476. // @param instruction_size Size of the instruction in bytes.
  477. //
  478. // @return Returns true if the instruction is a near absolute call.
  479. static bool IsNearRelativeCall(unsigned char* target,
  480. unsigned int instruction_size);
  481. // Helper routine that determines if a target instruction is a 64-bit MOV
  482. // that uses a RIP-relative displacement.
  483. //
  484. // @param target Pointer to instruction.
  485. //
  486. // @param instruction_size Size of the instruction in bytes.
  487. //
  488. // @return Returns true if the instruction is a MOV with displacement.
  489. static bool IsMovWithDisplacement(unsigned char* target,
  490. unsigned int instruction_size);
  491. // Helper routine that converts a short conditional jump instruction
  492. // to a near conditional jump in a target buffer. Note that the target
  493. // buffer must be within 2GB of the source for the near jump to work.
  494. //
  495. // A short conditional jump instruction is in the format:
  496. // 7x xx = Jcc rel8off
  497. //
  498. // @param source Pointer to instruction.
  499. //
  500. // @param instruction_size Size of the instruction.
  501. //
  502. // @param target Target buffer to write the new instruction.
  503. //
  504. // @param target_bytes Pointer to a buffer that contains the size
  505. // of the target instruction, in bytes.
  506. //
  507. // @param target_size Size of the target buffer.
  508. //
  509. // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error.
  510. static SideStepError PatchShortConditionalJump(unsigned char* source,
  511. unsigned int instruction_size,
  512. unsigned char* target,
  513. unsigned int* target_bytes,
  514. unsigned int target_size);
  515. static SideStepError PatchShortJump(unsigned char* source,
  516. unsigned int instruction_size,
  517. unsigned char* target,
  518. unsigned int* target_bytes,
  519. unsigned int target_size);
  520. // Helper routine that converts an instruction that will convert various
  521. // jump-like instructions to corresponding instructions in the target buffer.
  522. // What this routine does is fix up the relative offsets contained in jump
  523. // instructions to point back to the original target routine. Like with
  524. // PatchShortConditionalJump, the target buffer must be within 2GB of the
  525. // source.
  526. //
  527. // We currently handle the following instructions:
  528. //
  529. // E9 xx xx xx xx = JMP rel32off
  530. // 0F 8x xx xx xx xx = Jcc rel32off
  531. // FF /2 xx xx xx xx = CALL reg/mem32/mem64
  532. // E8 xx xx xx xx = CALL rel32off
  533. //
  534. // It should not be hard to update this function to support other
  535. // instructions that jump to relative targets.
  536. //
  537. // @param source Pointer to instruction.
  538. //
  539. // @param instruction_size Size of the instruction.
  540. //
  541. // @param target Target buffer to write the new instruction.
  542. //
  543. // @param target_bytes Pointer to a buffer that contains the size
  544. // of the target instruction, in bytes.
  545. //
  546. // @param target_size Size of the target buffer.
  547. //
  548. // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error.
  549. static SideStepError PatchNearJumpOrCall(unsigned char* source,
  550. unsigned int instruction_size,
  551. unsigned char* target,
  552. unsigned int* target_bytes,
  553. unsigned int target_size);
  554. // Helper routine that patches a 64-bit MOV instruction with a RIP-relative
  555. // displacement. The target buffer must be within 2GB of the source.
  556. //
  557. // 48 8B 0D XX XX XX XX = MOV rel32off
  558. //
  559. // @param source Pointer to instruction.
  560. //
  561. // @param instruction_size Size of the instruction.
  562. //
  563. // @param target Target buffer to write the new instruction.
  564. //
  565. // @param target_bytes Pointer to a buffer that contains the size
  566. // of the target instruction, in bytes.
  567. //
  568. // @param target_size Size of the target buffer.
  569. //
  570. // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error.
  571. static SideStepError PatchMovWithDisplacement(unsigned char* source,
  572. unsigned int instruction_size,
  573. unsigned char* target,
  574. unsigned int* target_bytes,
  575. unsigned int target_size);
  576. };
  577. }; // namespace sidestep
  578. #endif // GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_