28 static inline quintptr toQuintptr(
const void *ptr)
30 return *(quintptr*)ptr;
33 static inline int getVtableSize(quintptr **obj)
35 quintptr *begin = *obj;
37 if ((int64_t)*begin == 0 or (int64_t)*begin < QSysInfo::WordSize)
41 return begin - *obj + 2;
44 static inline quintptr *getVtableOfObject(
const void *obj)
46 return *(quintptr**)obj;
50 static quintptr *getVtableOfClass()
52 QByteArray vtable_symbol(
typeid(T).name());
53 vtable_symbol.prepend(
"_ZTV");
55 quintptr *vfptr_t1 =
reinterpret_cast<quintptr*
>(resolve(vtable_symbol.constData()));
57 return vfptr_t1 ? adjustToEntry(vfptr_t1) :
nullptr;
60 static int getDestructFunIndex(quintptr **obj, std::function<
void(
void)> destoryObjFun);
61 static constexpr const QObject *getQObject(...) {
return nullptr;}
62 static constexpr const QObject *getQObject(
const QObject *obj) {
return obj;}
63 static void autoCleanVtable(
const void *obj);
64 static bool ensureVtable(
const void *obj, std::function<
void(
void)> destoryObjFun);
65 static bool hasVtable(
const void *obj);
66 static void resetVtable(
const void *obj);
67 static quintptr resetVfptrFun(
const void *obj, quintptr functionOffset);
68 static quintptr originalFun(
const void *obj, quintptr functionOffset);
69 static bool forceWriteMemory(
void *adr,
const void *data,
size_t length);
70 static QFunctionPointer resolve(
const char *symbol);
76 template<
typename Fun1,
typename Fun2>
77 static bool overrideVfptrFun(quintptr *vfptr_t1, Fun1 fun1, quintptr *vfptr_t2, Fun2 fun2,
bool forceWrite)
79 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
80 typedef QtPrivate::FunctionPointer<Fun2> FunInfo2;
84 "Function1 and Function2 arguments are not compatible.");
85 Q_STATIC_ASSERT_X((
CheckCompatibleArguments<QtPrivate::List<typename FunInfo1::ReturnType>, QtPrivate::List<typename FunInfo2::ReturnType>>::value),
86 "Function1 and Function2 return type are not compatible..");
89 quintptr fun1_offset = toQuintptr(&fun1);
90 quintptr fun2_offset = toQuintptr(&fun2);
92 if (fun1_offset < 0 || fun1_offset > UINT_LEAST16_MAX)
95 quintptr *vfun = vfptr_t1 + fun1_offset /
sizeof(quintptr);
98 if (fun2_offset <= UINT_LEAST16_MAX) {
99 fun2_offset = *(vfptr_t2 + fun2_offset /
sizeof(quintptr));
103 return forceWriteMemory(vfun, &fun2_offset,
sizeof(fun2_offset));
110 template<
typename Fun1,
typename Fun2>
111 static bool overrideVfptrFun(
const typename QtPrivate::FunctionPointer<Fun1>::Object *t1, Fun1 fun1,
112 const typename QtPrivate::FunctionPointer<Fun2>::Object *t2, Fun2 fun2)
114 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
116 class OverrideDestruct :
public FunInfo1::Object { ~OverrideDestruct()
override;};
118 if (!ensureVtable((
void*)t1, std::bind(&_destory_helper<typename FunInfo1::Object>, t1))) {
122 quintptr *vfptr_t1 = getVtableOfObject(t1);
123 quintptr *vfptr_t2 = getVtableOfObject(t2);
125 bool ok = overrideVfptrFun(vfptr_t1, fun1, vfptr_t2, fun2,
false);
135 template<
typename Class,
typename Fun1,
typename Fun2>
136 static bool overrideVfptrFun(Fun1 fun1,
const typename QtPrivate::FunctionPointer<Fun2>::Object *t2, Fun2 fun2)
138 quintptr *vfptr_t1 = getVtableOfClass<Class>();
144 quintptr *vfptr_t2 = getVtableOfObject(t2);
146 return overrideVfptrFun(vfptr_t1, fun1, vfptr_t2, fun2,
true);
149 template<
typename Fun1,
typename Fun2>
150 static bool overrideVfptrFun(Fun1 fun1,
const typename QtPrivate::FunctionPointer<Fun2>::Object *t2, Fun2 fun2)
152 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
153 return overrideVfptrFun<typename FunInfo1::Object>(fun1, t2, fun2);
157 template<
class Obj,
typename Ret,
typename... Args>
struct FunctionPointer<Ret (Obj::*) (Args...)>
159 typedef QtPrivate::List<Obj*, Args...> Arguments;
161 template<
class Obj,
typename Ret,
typename... Args>
struct FunctionPointer<Ret (Obj::*) (Args...) const>
163 typedef QtPrivate::List<Obj*, Args...> Arguments;
165 template<
typename Fun1,
typename Fun2>
166 static typename std::enable_if<QtPrivate::FunctionPointer<Fun2>::ArgumentCount >= 0,
bool>::type
169 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
170 typedef QtPrivate::FunctionPointer<Fun2> FunInfo2;
172 Q_STATIC_ASSERT(!FunInfo2::IsPointerToMemberFunction);
175 "Function1 and Function2 arguments are not compatible.");
176 Q_STATIC_ASSERT_X((
CheckCompatibleArguments<QtPrivate::List<typename FunInfo1::ReturnType>, QtPrivate::List<typename FunInfo2::ReturnType>>::value),
177 "Function1 and Function2 return type are not compatible..");
180 quintptr fun1_offset = toQuintptr(&fun1);
181 quintptr fun2_offset = toQuintptr(&fun2);
183 if (fun1_offset > UINT_LEAST16_MAX)
186 quintptr *vfun = vfptr_t1 + fun1_offset /
sizeof(quintptr);
189 return forceWriteMemory(vfun, &fun2_offset,
sizeof(fun2_offset));
196 template<
typename StdFun,
typename Func>
struct StdFunWrap {};
197 template<
typename StdFun,
class Obj,
typename Ret,
typename... Args>
199 typedef std::function<Ret(Obj*, Args...)> StdFunType;
200 static inline StdFunType fun(StdFunType f,
bool check =
true) {
201 static StdFunType fun = f;
202 static bool initialized =
false;
203 if (initialized && check)
204 qCWarning(vtableHook,
"The StdFunWrap is dirty! Don't use std::bind(use lambda functions).");
208 static Ret call(Obj *o, Args... args) {
209 return fun(call,
false)(o, std::forward<Args>(args)...);
212 template<
typename StdFun,
class Obj,
typename Ret,
typename... Args>
215 template<
typename Fun1,
typename Fun2>
216 static inline typename std::enable_if<QtPrivate::FunctionPointer<Fun2>::ArgumentCount == -1,
bool>::type
217 overrideVfptrFun(quintptr *vfptr_t1, Fun1 fun1, Fun2 fun2,
bool forceWrite)
219 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
220 const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<Fun2, typename FunctionPointer<Fun1>::Arguments>::Value;
222 Q_STATIC_ASSERT_X((FunctorArgumentCount >= 0),
223 "Function1 and Function2 arguments are not compatible.");
224 const int Fun2ArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0;
225 typedef typename QtPrivate::FunctorReturnType<Fun2, typename QtPrivate::List_Left<typename FunctionPointer<Fun1>::Arguments, Fun2ArgumentCount>::Value>::Value Fun2ReturnType;
227 Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<Fun2ReturnType, typename FunInfo1::ReturnType>::value),
228 "Function1 and Function2 return type are not compatible.");
241 template<
typename Fun1,
typename Fun2>
242 static bool overrideVfptrFun(
const typename QtPrivate::FunctionPointer<Fun1>::Object *t1, Fun1 fun1, Fun2 fun2)
244 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
248 if (!ensureVtable((
void*)t1, std::bind(&_destory_helper<typename FunInfo1::Object>, t1))) {
252 bool ok = overrideVfptrFun(getVtableOfObject(t1), fun1, fun2,
false);
262 template<
typename Class,
typename Fun1,
typename Fun2>
263 static bool overrideVfptrFun(Fun1 fun1, Fun2 fun2)
265 quintptr *vfptr_t1 = getVtableOfClass<Class>();
271 return overrideVfptrFun(vfptr_t1, fun1, fun2,
true);
274 template<
typename Fun1,
typename Fun2>
275 static bool overrideVfptrFun(Fun1 fun1, Fun2 fun2)
277 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
278 return overrideVfptrFun<typename FunInfo1::Object>(fun1, fun2);
281 template<
typename Fun1>
282 static bool resetVfptrFun(
const typename QtPrivate::FunctionPointer<Fun1>::Object *obj, Fun1 fun)
284 return resetVfptrFun((
void*)obj, toQuintptr(&fun)) > 0;
287 template<
typename Fun>
288 static Fun originalFun(
const typename QtPrivate::FunctionPointer<Fun>::Object *obj, Fun fun)
290 quintptr o_fun = originalFun((
void*)obj, toQuintptr(&fun));
292 return *
reinterpret_cast<Fun*
>(o_fun);
295 template<
typename Fun,
typename... Args>
296 static typename QtPrivate::FunctionPointer<Fun>::ReturnType
297 callOriginalFun(
typename QtPrivate::FunctionPointer<Fun>::Object *obj, Fun fun, Args&&... args)
299 quintptr fun_offset = toQuintptr(&fun);
305 *(vfptr + offset /
sizeof(quintptr)) = oldFun;
307 quintptr *vfptr =
nullptr;
314 rvf.vfptr = *(quintptr**)(obj);
315 rvf.offset = fun_offset;
316 rvf.oldFun = DVtableHook::resetVfptrFun((
void*)obj, fun_offset);
319 qCWarning(vtableHook) <<
"Reset the function failed, object: " << obj;
324 return (obj->*fun)(std::forward<Args>(args)...);
328 static bool copyVtable(quintptr **obj);
329 static bool clearGhostVtable(
const void *obj);
330#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
331 Q_DECL_DEPRECATED
static bool isFinalClass(quintptr *obj);
332 Q_DECL_DEPRECATED
static quintptr **adjustThis(quintptr *obj);
335 template <
typename T>
336 static T adjustToTop(T obj)
339 using fundamentalType =
typename std::remove_cv<typename std::remove_pointer<T>::type>::type;
340 return obj -
static_cast<fundamentalType
>(2);
343 template <
typename T>
344 static T adjustToEntry(T obj)
347 using fundamentalType =
typename std::remove_cv<typename std::remove_pointer<T>::type>::type;
348 return obj +
static_cast<fundamentalType
>(2);
352 static void _destory_helper(
const T *obj) {
356 static QMap<quintptr**, quintptr*> objToOriginalVfptr;
357 static QMap<const void*, quintptr*> objToGhostVfptr;
358 static QMap<const void*, quintptr> objDestructFun;