8#include <dtkcore_global.h>
22 static inline quintptr toQuintptr(
const void *ptr)
24 return *(quintptr*)ptr;
27 static inline int getVtableSize(quintptr **obj)
29 quintptr *begin = *obj;
30 while(*begin) ++begin;
34 static inline quintptr *getVtableOfObject(
const void *obj)
36 return *(quintptr**)obj;
40 static quintptr *getVtableOfClass()
42 QByteArray vtable_symbol(
typeid(T).name());
43 vtable_symbol.prepend(
"_ZTV");
45 quintptr *vfptr_t1 =
reinterpret_cast<quintptr*
>(resolve(vtable_symbol.constData()));
54 static int getDestructFunIndex(quintptr **obj, std::function<
void(
void)> destoryObjFun);
55 static constexpr const QObject *getQObject(...) {
return nullptr;}
56 static constexpr const QObject *getQObject(
const QObject *obj) {
return obj;}
57 static void autoCleanVtable(
const void *obj);
58 static bool ensureVtable(
const void *obj, std::function<
void(
void)> destoryObjFun);
59 static bool hasVtable(
const void *obj);
60 static void resetVtable(
const void *obj);
61 static quintptr resetVfptrFun(
const void *obj, quintptr functionOffset);
62 static quintptr originalFun(
const void *obj, quintptr functionOffset);
63 static bool forceWriteMemory(
void *adr,
const void *data,
size_t length);
64 static QFunctionPointer resolve(
const char *symbol);
70 template<
typename Fun1,
typename Fun2>
71 static bool overrideVfptrFun(quintptr *vfptr_t1, Fun1 fun1, quintptr *vfptr_t2, Fun2 fun2,
bool forceWrite)
73 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
74 typedef QtPrivate::FunctionPointer<Fun2> FunInfo2;
78 "Function1 and Function2 arguments are not compatible.");
79 Q_STATIC_ASSERT_X((
CheckCompatibleArguments<QtPrivate::List<typename FunInfo1::ReturnType>, QtPrivate::List<typename FunInfo2::ReturnType>>::value),
80 "Function1 and Function2 return type are not compatible..");
83 quintptr fun1_offset = toQuintptr(&fun1);
84 quintptr fun2_offset = toQuintptr(&fun2);
86 if (fun1_offset < 0 || fun1_offset > UINT_LEAST16_MAX)
89 quintptr *vfun = vfptr_t1 + fun1_offset /
sizeof(quintptr);
92 if (fun2_offset <= UINT_LEAST16_MAX) {
93 fun2_offset = *(vfptr_t2 + fun2_offset /
sizeof(quintptr));
97 return forceWriteMemory(vfun, &fun2_offset,
sizeof(fun2_offset));
104 template<
typename Fun1,
typename Fun2>
105 static bool overrideVfptrFun(
const typename QtPrivate::FunctionPointer<Fun1>::Object *t1, Fun1 fun1,
106 const typename QtPrivate::FunctionPointer<Fun2>::Object *t2, Fun2 fun2)
108 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
110 class OverrideDestruct :
public FunInfo1::Object { ~OverrideDestruct()
override;};
112 if (!ensureVtable((
void*)t1, std::bind(&_destory_helper<typename FunInfo1::Object>, t1))) {
116 quintptr *vfptr_t1 = getVtableOfObject(t1);
117 quintptr *vfptr_t2 = getVtableOfObject(t2);
119 bool ok = overrideVfptrFun(vfptr_t1, fun1, vfptr_t2, fun2,
false);
129 template<
typename Class,
typename Fun1,
typename Fun2>
130 static bool overrideVfptrFun(Fun1 fun1,
const typename QtPrivate::FunctionPointer<Fun2>::Object *t2, Fun2 fun2)
132 quintptr *vfptr_t1 = getVtableOfClass<Class>();
138 quintptr *vfptr_t2 = getVtableOfObject(t2);
140 return overrideVfptrFun(vfptr_t1, fun1, vfptr_t2, fun2,
true);
143 template<
typename Fun1,
typename Fun2>
144 static bool overrideVfptrFun(Fun1 fun1,
const typename QtPrivate::FunctionPointer<Fun2>::Object *t2, Fun2 fun2)
146 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
147 return overrideVfptrFun<typename FunInfo1::Object>(fun1, t2, fun2);
151 template<
class Obj,
typename Ret,
typename... Args>
struct FunctionPointer<Ret (Obj::*) (Args...)>
153 typedef QtPrivate::List<Obj*, Args...> Arguments;
155 template<
class Obj,
typename Ret,
typename... Args>
struct FunctionPointer<Ret (Obj::*) (Args...) const>
157 typedef QtPrivate::List<Obj*, Args...> Arguments;
159 template<
typename Fun1,
typename Fun2>
160 static typename std::enable_if<QtPrivate::FunctionPointer<Fun2>::ArgumentCount >= 0,
bool>::type
163 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
164 typedef QtPrivate::FunctionPointer<Fun2> FunInfo2;
166 Q_STATIC_ASSERT(!FunInfo2::IsPointerToMemberFunction);
169 "Function1 and Function2 arguments are not compatible.");
170 Q_STATIC_ASSERT_X((
CheckCompatibleArguments<QtPrivate::List<typename FunInfo1::ReturnType>, QtPrivate::List<typename FunInfo2::ReturnType>>::value),
171 "Function1 and Function2 return type are not compatible..");
174 quintptr fun1_offset = toQuintptr(&fun1);
175 quintptr fun2_offset = toQuintptr(&fun2);
177 if (fun1_offset < 0 || fun1_offset > UINT_LEAST16_MAX)
180 quintptr *vfun = vfptr_t1 + fun1_offset /
sizeof(quintptr);
183 return forceWriteMemory(vfun, &fun2_offset,
sizeof(fun2_offset));
190 template<
typename StdFun,
typename Func>
struct StdFunWrap {};
191 template<
typename StdFun,
class Obj,
typename Ret,
typename... Args>
193 typedef std::function<Ret(Obj*, Args...)> StdFunType;
194 static inline StdFunType fun(StdFunType f,
bool check =
true) {
195 static StdFunType fun = f;
196 static bool initialized =
false;
197 if (initialized && check) {
198 qWarning(
"The StdFunWrap is dirty! Don't use std::bind(use lambda functions).");
203 static Ret call(Obj *o, Args... args) {
204 return fun(call,
false)(o, std::forward<Args>(args)...);
207 template<
typename StdFun,
class Obj,
typename Ret,
typename... Args>
210 template<
typename Fun1,
typename Fun2>
211 static inline typename std::enable_if<QtPrivate::FunctionPointer<Fun2>::ArgumentCount == -1,
bool>::type
212 overrideVfptrFun(quintptr *vfptr_t1, Fun1 fun1, Fun2 fun2,
bool forceWrite)
214 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
215 const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<Fun2, typename FunctionPointer<Fun1>::Arguments>::Value;
217 Q_STATIC_ASSERT_X((FunctorArgumentCount >= 0),
218 "Function1 and Function2 arguments are not compatible.");
219 const int Fun2ArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0;
220 typedef typename QtPrivate::FunctorReturnType<Fun2, typename QtPrivate::List_Left<typename FunctionPointer<Fun1>::Arguments, Fun2ArgumentCount>::Value>::Value Fun2ReturnType;
222 Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<Fun2ReturnType, typename FunInfo1::ReturnType>::value),
223 "Function1 and Function2 return type are not compatible.");
236 template<
typename Fun1,
typename Fun2>
237 static bool overrideVfptrFun(
const typename QtPrivate::FunctionPointer<Fun1>::Object *t1, Fun1 fun1, Fun2 fun2)
239 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
243 if (!ensureVtable((
void*)t1, std::bind(&_destory_helper<typename FunInfo1::Object>, t1))) {
247 bool ok = overrideVfptrFun(getVtableOfObject(t1), fun1, fun2,
false);
257 template<
typename Class,
typename Fun1,
typename Fun2>
258 static bool overrideVfptrFun(Fun1 fun1, Fun2 fun2)
260 quintptr *vfptr_t1 = getVtableOfClass<Class>();
266 return overrideVfptrFun(vfptr_t1, fun1, fun2,
true);
269 template<
typename Fun1,
typename Fun2>
270 static bool overrideVfptrFun(Fun1 fun1, Fun2 fun2)
272 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
273 return overrideVfptrFun<typename FunInfo1::Object>(fun1, fun2);
276 template<
typename Fun1>
277 static bool resetVfptrFun(
const typename QtPrivate::FunctionPointer<Fun1>::Object *obj, Fun1 fun)
279 return resetVfptrFun((
void*)obj, toQuintptr(&fun)) > 0;
282 template<
typename Fun>
283 static Fun originalFun(
const typename QtPrivate::FunctionPointer<Fun>::Object *obj, Fun fun)
285 quintptr o_fun = originalFun((
void*)obj, toQuintptr(&fun));
287 return *
reinterpret_cast<Fun*
>(o_fun);
290 template<
typename Fun,
typename... Args>
291 static typename QtPrivate::FunctionPointer<Fun>::ReturnType
292 callOriginalFun(
typename QtPrivate::FunctionPointer<Fun>::Object *obj, Fun fun, Args&&... args)
294 quintptr fun_offset = toQuintptr(&fun);
300 *(vfptr + offset /
sizeof(quintptr)) = oldFun;
302 quintptr *vfptr =
nullptr;
309 rvf.vfptr = *(quintptr**)(obj);
310 rvf.offset = fun_offset;
311 rvf.oldFun = DVtableHook::resetVfptrFun((
void*)obj, fun_offset);
314 qWarning() <<
"Reset the function failed, object:" << obj;
319 return (obj->*fun)(std::forward<Args>(args)...);
323 static bool copyVtable(quintptr **obj);
324 static bool clearGhostVtable(
const void *obj);
327 static void _destory_helper(
const T *obj) {
331 static QMap<quintptr**, quintptr*> objToOriginalVfptr;
332 static QMap<const void*, quintptr*> objToGhostVfptr;
333 static QMap<const void*, quintptr> objDestructFun;
Definition: dvtablehook.h:66
Definition: dvtablehook.h:20
static bool ::type overrideVfptrFun(quintptr *vfptr_t1, Fun1 fun1, Fun2 fun2, bool forceWrite)
Definition: dvtablehook.h:161
static bool overrideVfptrFun(const typename QtPrivate::FunctionPointer< Fun1 >::Object *t1, Fun1 fun1, Fun2 fun2)
Definition: dvtablehook.h:237
static bool overrideVfptrFun(quintptr *vfptr_t1, Fun1 fun1, quintptr *vfptr_t2, Fun2 fun2, bool forceWrite)
Definition: dvtablehook.h:71
Definition: dvtablehook.h:67
Definition: dvtablehook.h:150
Definition: dvtablehook.h:190