24#include <dtkcore_global.h>
38 static inline quintptr toQuintptr(
const void *ptr)
40 return *(quintptr*)ptr;
43 static inline int getVtableSize(quintptr **obj)
45 quintptr *begin = *obj;
46 while(*begin) ++begin;
50 static inline quintptr *getVtableOfObject(
const void *obj)
52 return *(quintptr**)obj;
56 static quintptr *getVtableOfClass()
58 QByteArray vtable_symbol(
typeid(T).name());
59 vtable_symbol.prepend(
"_ZTV");
61 quintptr *vfptr_t1 =
reinterpret_cast<quintptr*
>(resolve(vtable_symbol.constData()));
70 static int getDestructFunIndex(quintptr **obj, std::function<
void(
void)> destoryObjFun);
71 static constexpr const QObject *getQObject(...) {
return nullptr;}
72 static constexpr const QObject *getQObject(
const QObject *obj) {
return obj;}
73 static void autoCleanVtable(
const void *obj);
74 static bool ensureVtable(
const void *obj, std::function<
void(
void)> destoryObjFun);
75 static bool hasVtable(
const void *obj);
76 static void resetVtable(
const void *obj);
77 static quintptr resetVfptrFun(
const void *obj, quintptr functionOffset);
78 static quintptr originalFun(
const void *obj, quintptr functionOffset);
79 static bool forceWriteMemory(
void *adr,
const void *data,
size_t length);
80 static QFunctionPointer resolve(
const char *symbol);
86 template<
typename Fun1,
typename Fun2>
87 static bool overrideVfptrFun(quintptr *vfptr_t1, Fun1 fun1, quintptr *vfptr_t2, Fun2 fun2,
bool forceWrite)
89 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
90 typedef QtPrivate::FunctionPointer<Fun2> FunInfo2;
94 "Function1 and Function2 arguments are not compatible.");
95 Q_STATIC_ASSERT_X((
CheckCompatibleArguments<QtPrivate::List<typename FunInfo1::ReturnType>, QtPrivate::List<typename FunInfo2::ReturnType>>::value),
96 "Function1 and Function2 return type are not compatible..");
99 quintptr fun1_offset = toQuintptr(&fun1);
100 quintptr fun2_offset = toQuintptr(&fun2);
102 if (fun1_offset < 0 || fun1_offset > UINT_LEAST16_MAX)
105 quintptr *vfun = vfptr_t1 + fun1_offset /
sizeof(quintptr);
108 if (fun2_offset <= UINT_LEAST16_MAX) {
109 fun2_offset = *(vfptr_t2 + fun2_offset /
sizeof(quintptr));
113 return forceWriteMemory(vfun, &fun2_offset,
sizeof(fun2_offset));
120 template<
typename Fun1,
typename Fun2>
121 static bool overrideVfptrFun(
const typename QtPrivate::FunctionPointer<Fun1>::Object *t1, Fun1 fun1,
122 const typename QtPrivate::FunctionPointer<Fun2>::Object *t2, Fun2 fun2)
124 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
126 class OverrideDestruct :
public FunInfo1::Object { ~OverrideDestruct()
override;};
128 if (!ensureVtable((
void*)t1, std::bind(&_destory_helper<typename FunInfo1::Object>, t1))) {
132 quintptr *vfptr_t1 = getVtableOfObject(t1);
133 quintptr *vfptr_t2 = getVtableOfObject(t2);
135 bool ok = overrideVfptrFun(vfptr_t1, fun1, vfptr_t2, fun2,
false);
145 template<
typename Class,
typename Fun1,
typename Fun2>
146 static bool overrideVfptrFun(Fun1 fun1,
const typename QtPrivate::FunctionPointer<Fun2>::Object *t2, Fun2 fun2)
148 quintptr *vfptr_t1 = getVtableOfClass<Class>();
154 quintptr *vfptr_t2 = getVtableOfObject(t2);
156 return overrideVfptrFun(vfptr_t1, fun1, vfptr_t2, fun2,
true);
159 template<
typename Fun1,
typename Fun2>
160 static bool overrideVfptrFun(Fun1 fun1,
const typename QtPrivate::FunctionPointer<Fun2>::Object *t2, Fun2 fun2)
162 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
163 return overrideVfptrFun<typename FunInfo1::Object>(fun1, t2, fun2);
167 template<
class Obj,
typename Ret,
typename... Args>
struct FunctionPointer<Ret (Obj::*) (Args...)>
169 typedef QtPrivate::List<Obj*, Args...> Arguments;
171 template<
class Obj,
typename Ret,
typename... Args>
struct FunctionPointer<Ret (Obj::*) (Args...) const>
173 typedef QtPrivate::List<Obj*, Args...> Arguments;
175 template<
typename Fun1,
typename Fun2>
176 static typename std::enable_if<QtPrivate::FunctionPointer<Fun2>::ArgumentCount >= 0,
bool>::type
179 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
180 typedef QtPrivate::FunctionPointer<Fun2> FunInfo2;
182 Q_STATIC_ASSERT(!FunInfo2::IsPointerToMemberFunction);
185 "Function1 and Function2 arguments are not compatible.");
186 Q_STATIC_ASSERT_X((
CheckCompatibleArguments<QtPrivate::List<typename FunInfo1::ReturnType>, QtPrivate::List<typename FunInfo2::ReturnType>>::value),
187 "Function1 and Function2 return type are not compatible..");
190 quintptr fun1_offset = toQuintptr(&fun1);
191 quintptr fun2_offset = toQuintptr(&fun2);
193 if (fun1_offset < 0 || fun1_offset > UINT_LEAST16_MAX)
196 quintptr *vfun = vfptr_t1 + fun1_offset /
sizeof(quintptr);
199 return forceWriteMemory(vfun, &fun2_offset,
sizeof(fun2_offset));
206 template<
typename StdFun,
typename Func>
struct StdFunWrap {};
207 template<
typename StdFun,
class Obj,
typename Ret,
typename... Args>
209 typedef std::function<Ret(Obj*, Args...)> StdFunType;
210 static inline StdFunType fun(StdFunType f,
bool check =
true) {
211 static StdFunType fun = f;
212 static bool initialized =
false;
213 if (initialized && check) {
214 qWarning(
"The StdFunWrap is dirty! Don't use std::bind(use lambda functions).");
219 static Ret call(Obj *o, Args... args) {
220 return fun(call,
false)(o, std::forward<Args>(args)...);
223 template<
typename StdFun,
class Obj,
typename Ret,
typename... Args>
226 template<
typename Fun1,
typename Fun2>
227 static inline typename std::enable_if<QtPrivate::FunctionPointer<Fun2>::ArgumentCount == -1,
bool>::type
228 overrideVfptrFun(quintptr *vfptr_t1, Fun1 fun1, Fun2 fun2,
bool forceWrite)
230 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
231 const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<Fun2, typename FunctionPointer<Fun1>::Arguments>::Value;
233 Q_STATIC_ASSERT_X((FunctorArgumentCount >= 0),
234 "Function1 and Function2 arguments are not compatible.");
235 const int Fun2ArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0;
236 typedef typename QtPrivate::FunctorReturnType<Fun2, typename QtPrivate::List_Left<typename FunctionPointer<Fun1>::Arguments, Fun2ArgumentCount>::Value>::Value Fun2ReturnType;
238 Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<Fun2ReturnType, typename FunInfo1::ReturnType>::value),
239 "Function1 and Function2 return type are not compatible.");
252 template<
typename Fun1,
typename Fun2>
253 static bool overrideVfptrFun(
const typename QtPrivate::FunctionPointer<Fun1>::Object *t1, Fun1 fun1, Fun2 fun2)
255 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
259 if (!ensureVtable((
void*)t1, std::bind(&_destory_helper<typename FunInfo1::Object>, t1))) {
263 bool ok = overrideVfptrFun(getVtableOfObject(t1), fun1, fun2,
false);
273 template<
typename Class,
typename Fun1,
typename Fun2>
274 static bool overrideVfptrFun(Fun1 fun1, Fun2 fun2)
276 quintptr *vfptr_t1 = getVtableOfClass<Class>();
282 return overrideVfptrFun(vfptr_t1, fun1, fun2,
true);
285 template<
typename Fun1,
typename Fun2>
286 static bool overrideVfptrFun(Fun1 fun1, Fun2 fun2)
288 typedef QtPrivate::FunctionPointer<Fun1> FunInfo1;
289 return overrideVfptrFun<typename FunInfo1::Object>(fun1, fun2);
292 template<
typename Fun1>
293 static bool resetVfptrFun(
const typename QtPrivate::FunctionPointer<Fun1>::Object *obj, Fun1 fun)
295 return resetVfptrFun((
void*)obj, toQuintptr(&fun)) > 0;
298 template<
typename Fun>
299 static Fun originalFun(
const typename QtPrivate::FunctionPointer<Fun>::Object *obj, Fun fun)
301 quintptr o_fun = originalFun((
void*)obj, toQuintptr(&fun));
303 return *
reinterpret_cast<Fun*
>(o_fun);
306 template<
typename Fun,
typename... Args>
307 static typename QtPrivate::FunctionPointer<Fun>::ReturnType
308 callOriginalFun(
typename QtPrivate::FunctionPointer<Fun>::Object *obj, Fun fun, Args&&... args)
310 quintptr fun_offset = toQuintptr(&fun);
316 *(vfptr + offset /
sizeof(quintptr)) = oldFun;
318 quintptr *vfptr =
nullptr;
325 rvf.vfptr = *(quintptr**)(obj);
326 rvf.offset = fun_offset;
327 rvf.oldFun = DVtableHook::resetVfptrFun((
void*)obj, fun_offset);
330 qWarning() <<
"Reset the function failed, object:" << obj;
335 return (obj->*fun)(std::forward<Args>(args)...);
339 static bool copyVtable(quintptr **obj);
340 static bool clearGhostVtable(
const void *obj);
343 static void _destory_helper(
const T *obj) {
347 static QMap<quintptr**, quintptr*> objToOriginalVfptr;
348 static QMap<const void*, quintptr*> objToGhostVfptr;
349 static QMap<const void*, quintptr> objDestructFun;
Definition: dvtablehook.h:82
Definition: dvtablehook.h:36
static bool ::type overrideVfptrFun(quintptr *vfptr_t1, Fun1 fun1, Fun2 fun2, bool forceWrite)
Definition: dvtablehook.h:177
static bool overrideVfptrFun(const typename QtPrivate::FunctionPointer< Fun1 >::Object *t1, Fun1 fun1, Fun2 fun2)
Definition: dvtablehook.h:253
static bool overrideVfptrFun(quintptr *vfptr_t1, Fun1 fun1, quintptr *vfptr_t2, Fun2 fun2, bool forceWrite)
Definition: dvtablehook.h:87
Definition: dvtablehook.h:83
Definition: dvtablehook.h:166
Definition: dvtablehook.h:206