1From c050505bbee806f7389d1c7360eef08d6a39aad6 Mon Sep 17 00:00:00 2001 2From: Zhu Guodong <zhuguodong0001@163.com> 3Date: Fri, 10 May 2024 18:33:50 +0800 4Subject: [PATCH] mockcpp patch 5 6--- 7 include/mockcpp/JmpCode.h | 1 + 8 include/mockcpp/mockcpp.h | 6 +++- 9 src/JmpCode.cpp | 16 ++++++++- 10 src/JmpCodeAARCH64.h | 69 +++++++++++++++++++++++++++++++++++++++ 11 src/JmpCodeARM32.h | 36 ++++++++++++++++++++ 12 src/JmpCodeArch.h | 20 +++++++++++- 13 src/JmpCodeX64.h | 3 +- 14 src/JmpCodeX86.h | 3 +- 15 src/JmpOnlyApiHook.cpp | 1 + 16 src/UnixCodeModifier.cpp | 2 ++ 17 10 files changed, 152 insertions(+), 5 deletions(-) 18 create mode 100644 src/JmpCodeAARCH64.h 19 create mode 100644 src/JmpCodeARM32.h 20 21diff --git a/include/mockcpp/JmpCode.h b/include/mockcpp/JmpCode.h 22index 26f77b0..ed0fac6 100644 23--- a/include/mockcpp/JmpCode.h 24+++ b/include/mockcpp/JmpCode.h 25@@ -33,6 +33,7 @@ struct JmpCode 26 27 void* getCodeData() const; 28 size_t getCodeSize() const; 29+ void flushCache() const; 30 private: 31 JmpCodeImpl* This; 32 }; 33diff --git a/include/mockcpp/mockcpp.h b/include/mockcpp/mockcpp.h 34index 306bc7a..8cc385d 100644 35--- a/include/mockcpp/mockcpp.h 36+++ b/include/mockcpp/mockcpp.h 37@@ -39,7 +39,11 @@ 38 #endif 39 40 41-#if ( defined (__LP64__) \ 42+#if defined (__aarch64__) 43+#define BUILD_FOR_AARCH64 44+#elif defined (__arm__) 45+#define BUILD_FOR_ARM32 46+#elif ( defined (__LP64__) \ 47 || defined (__64BIT__) \ 48 || defined (_LP64) \ 49 || ((defined(__WORDSIZE)) && (__WORDSIZE == 64)) \ 50diff --git a/src/JmpCode.cpp b/src/JmpCode.cpp 51index 35794fb..6aac228 100644 52--- a/src/JmpCode.cpp 53+++ b/src/JmpCode.cpp 54@@ -30,6 +30,7 @@ struct JmpCodeImpl 55 //////////////////////////////////////////////// 56 JmpCodeImpl(const void* from, const void* to) 57 { 58+ m_from = from; 59 ::memcpy(m_code, jmpCodeTemplate, JMP_CODE_SIZE); 60 SET_JMP_CODE(m_code, from, to); 61 } 62@@ -47,7 +48,14 @@ struct JmpCodeImpl 63 } 64 65 //////////////////////////////////////////////// 66+ void flushCache() const 67+ { 68+ FLUSH_CACHE((const char *)m_from, JMP_CODE_SIZE); 69+ } 70 71+ //////////////////////////////////////////////// 72+ 73+ const void *m_from; 74 unsigned char m_code[JMP_CODE_SIZE]; 75 }; 76 77@@ -77,5 +85,11 @@ JmpCode::getCodeSize() const 78 return This->getCodeSize(); 79 } 80 81-MOCKCPP_NS_END 82+/////////////////////////////////////////////////// 83+void 84+JmpCode::flushCache() const 85+{ 86+ return This->flushCache(); 87+} 88 89+MOCKCPP_NS_END 90diff --git a/src/JmpCodeAARCH64.h b/src/JmpCodeAARCH64.h 91new file mode 100644 92index 0000000..4f5e90b 93--- /dev/null 94+++ b/src/JmpCodeAARCH64.h 95@@ -0,0 +1,69 @@ 96+/*** 97+ mockcpp is a C/C++ mock framework. 98+ Copyright [2008] [Darwin Yuan <darwin.yuan@gmail.com>] 99+ [Chen Guodong <sinojelly@gmail.com>] 100+ Licensed under the Apache License, Version 2.0 (the "License"); 101+ you may not use this file except in compliance with the License. 102+ You may obtain a copy of the License at 103+ 104+ http://www.apache.org/licenses/LICENSE-2.0 105+ 106+ Unless required by applicable law or agreed to in writing, software 107+ distributed under the License is distributed on an "AS IS" BASIS, 108+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 109+ See the License for the specific language governing permissions and 110+ limitations under the License. 111+***/ 112+#ifndef __MOCKCPP_JMP_CODE_AARCH64_H__ 113+#define __MOCKCPP_JMP_CODE_AARCH64_H__ 114+ 115+#include <asm/unistd.h> 116+#include <errno.h> 117+#include <fcntl.h> 118+#include <stdio.h> 119+#include <stdlib.h> 120+#include <sys/ioctl.h> 121+#include <sys/mman.h> 122+#include <sys/prctl.h> 123+#include <sys/stat.h> 124+#include <sys/syscall.h> 125+ 126+MOCKCPP_NS_START 127+ 128+struct l2cache_addr_range { 129+ uintptr_t start; 130+ uintptr_t end; 131+}; 132+ 133+MOCKCPP_NS_END 134+ 135+#define ADDR_ALIGN_UP(addr) ((((addr) + ((4096) - 1)) & (~((4096) - 1))) & 0xffffffffffffffff) 136+#define ADDR_ALIGN_DOWN(addr) (((addr) & (~((4096) - 1))) & 0xffffffffffffffff) 137+#define OUTER_CACHE_INV_RANGE _IOWR('S', 0x00, struct l2cache_addr_range) 138+#define OUTER_CACHE_CLEAN_RANGE _IOWR('S', 0x01, struct l2cache_addr_range) 139+#define OUTER_CACHE_FLUSH_RANGE _IOWR('S', 0x02, struct l2cache_addr_range) 140+#define L1_INV_I_CACHE _IOWR('S', 0x03, struct l2cache_addr_range) 141+#define D_TO_I_CACHE_FLUSH_RANGE _IOWR('S', 0x04, struct l2cache_addr_range) 142+ 143+const unsigned char jmpCodeTemplate[] = 144+ { 0x57, 0x00, 0x00, 0x58, 0xe0, 0x02, 0x1f, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 145+ 146+#define SET_SJMP_CODE(base, from, to) do { \ 147+ using instruct_t = signed int; \ 148+ instruct_t offset = (intptr_t)to - (intptr_t)from; \ 149+ offset = ((offset >> 2) & 0x03FFFFFF) | 0x14000000; \ 150+ *(instruct_t *)(base) = offset; \ 151+ } while(0) 152+ 153+#define SET_JMP_CODE(base, from, to) do { \ 154+ *(void **)(base + 8) = (void *)to; \ 155+ } while(0) 156+ 157+#define FLUSH_CACHE(from, length) do { \ 158+ struct l2cache_addr_range usr_data; \ 159+ usr_data.start = ADDR_ALIGN_DOWN((unsigned long long)from); \ 160+ usr_data.end = ADDR_ALIGN_UP((unsigned long long)from) + length; \ 161+ __builtin___clear_cache((char *)usr_data.start, (char *)usr_data.end); \ 162+} while (0) 163+ 164+#endif 165diff --git a/src/JmpCodeARM32.h b/src/JmpCodeARM32.h 166new file mode 100644 167index 0000000..1eec42b 168--- /dev/null 169+++ b/src/JmpCodeARM32.h 170@@ -0,0 +1,36 @@ 171+/*** 172+ mockcpp is a C/C++ mock framework. 173+ Copyright [2008] [Darwin Yuan <darwin.yuan@gmail.com>] 174+ [Chen Guodong <sinojelly@gmail.com>] 175+ Licensed under the Apache License, Version 2.0 (the "License"); 176+ you may not use this file except in compliance with the License. 177+ You may obtain a copy of the License at 178+ 179+ http://www.apache.org/licenses/LICENSE-2.0 180+ 181+ Unless required by applicable law or agreed to in writing, software 182+ distributed under the License is distributed on an "AS IS" BASIS, 183+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 184+ See the License for the specific language governing permissions and 185+ limitations under the License. 186+***/ 187+#ifndef __MOCKCPP_JMP_CODE_ARM32_H__ 188+#define __MOCKCPP_JMP_CODE_ARM32_H__ 189+ 190+#include <stdlib.h> 191+ 192+const unsigned char jmpCodeTemplate[] = 193+ { 0xEA, 0x00, 0x00, 0x00 }; 194+ 195+#define SET_JMP_CODE(base, from, to) do { \ 196+ int offset = (int)to - (int)from - 8; \ 197+ offset = (offset >> 2) & 0x00FFFFFF; \ 198+ int code = *(int *)(base) | offset; \ 199+ *(int *)(base) = changeByteOrder(code); \ 200+ } while(0) 201+ 202+#define FLUSH_CACHE(from, length) do { \ 203+ ::system("echo 3 > /proc/sys/vm/drop_caches"); \ 204+} while (0) 205+ 206+#endif 207diff --git a/src/JmpCodeArch.h b/src/JmpCodeArch.h 208index 26abd73..53353eb 100644 209--- a/src/JmpCodeArch.h 210+++ b/src/JmpCodeArch.h 211@@ -19,11 +19,29 @@ 212 213 #include <mockcpp/mockcpp.h> 214 215+template <typename T> 216+inline T changeByteOrder(const T v) { 217+ enum { S = sizeof(T) }; 218+ T rst = v; 219+ char *p = (char *)&rst; 220+ char tmp = 0; 221+ for (unsigned int i = 0; i < S / 2; ++i) { 222+ tmp = p[i]; 223+ p[i] = p[S - i - 1]; 224+ p [S - i - 1] = tmp; 225+ } 226+ 227+ return rst; 228+} 229+ 230 #if BUILD_FOR_X64 231 # include "JmpCodeX64.h" 232 #elif BUILD_FOR_X86 233 # include "JmpCodeX86.h" 234+#elif defined(BUILD_FOR_ARM32) 235+# include "JmpCodeARM32.h" 236+#elif defined(BUILD_FOR_AARCH64) 237+# include "JmpCodeAARCH64.h" 238 #endif 239 240 #endif 241- 242diff --git a/src/JmpCodeX64.h b/src/JmpCodeX64.h 243index 198507a..e5b4f31 100644 244--- a/src/JmpCodeX64.h 245+++ b/src/JmpCodeX64.h 246@@ -27,5 +27,6 @@ const unsigned char jmpCodeTemplate[] = 247 *(uintptr_t *)(base + 6) = (uintptr_t)to; \ 248 } while(0) 249 250-#endif 251+#define FLUSH_CACHE(from, length) ((void)0) 252 253+#endif 254diff --git a/src/JmpCodeX86.h b/src/JmpCodeX86.h 255index ebdc526..a06a02e 100644 256--- a/src/JmpCodeX86.h 257+++ b/src/JmpCodeX86.h 258@@ -23,5 +23,6 @@ const unsigned char jmpCodeTemplate[] = { 0xE9, 0x00, 0x00, 0x00, 0x00 }; 259 (unsigned long long)to - (unsigned long long)from - sizeof(jmpCodeTemplate); \ 260 } while(0) 261 262-#endif 263+#define FLUSH_CACHE(from, length) ((void)0) 264 265+#endif 266diff --git a/src/JmpOnlyApiHook.cpp b/src/JmpOnlyApiHook.cpp 267index d4cfa68..964828f 100644 268--- a/src/JmpOnlyApiHook.cpp 269+++ b/src/JmpOnlyApiHook.cpp 270@@ -68,6 +68,7 @@ struct JmpOnlyApiHookImpl 271 void changeCode(const void* data) 272 { 273 CodeModifier::modify(const_cast<void*>(m_api), data, m_jmpCode.getCodeSize()); 274+ m_jmpCode.flushCache(); 275 } 276 277 ///////////////////////////////////////////////////// 278diff --git a/src/UnixCodeModifier.cpp b/src/UnixCodeModifier.cpp 279index ab4014e..8e7dde9 100644 280--- a/src/UnixCodeModifier.cpp 281+++ b/src/UnixCodeModifier.cpp 282@@ -20,6 +20,7 @@ 283 #include <sys/mman.h> 284 285 #include <mockcpp/CodeModifier.h> 286+#include "JmpCodeArch.h" 287 288 #define PAGE_ALIGN_BITS 12 289 290@@ -39,6 +40,7 @@ bool CodeModifier::modify(void *dest, const void *src, size_t size) 291 292 ::memcpy(dest, src, size); 293 294+ FLUSH_CACHE(dest, size); 295 296 #if 0 297 #if BUILD_FOR_X86 298-- 2992.34.1 300