py_hooks.cc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include "hooks_py.h"
  2. #include "subsecond_time.h"
  3. #include "simulator.h"
  4. #include "hooks_manager.h"
  5. #include "magic_server.h"
  6. #include "syscall_model.h"
  7. #include "sim_api.h"
  8. static SInt64 hookCallbackResult(PyObject *pResult)
  9. {
  10. SInt64 result = -1;
  11. if (pResult == NULL)
  12. return -1;
  13. else if (PyInt_Check(pResult))
  14. result = PyInt_AsLong(pResult);
  15. else if (PyLong_Check(pResult))
  16. result = PyLong_AsLong(pResult);
  17. Py_DECREF(pResult);
  18. return result;
  19. }
  20. static SInt64 hookCallbackNone(UInt64 pFunc, UInt64)
  21. {
  22. PyObject *pResult = HooksPy::callPythonFunction((PyObject *)pFunc, NULL);
  23. return hookCallbackResult(pResult);
  24. }
  25. static SInt64 hookCallbackInt(UInt64 pFunc, UInt64 argument)
  26. {
  27. PyObject *pResult = HooksPy::callPythonFunction((PyObject *)pFunc, Py_BuildValue("(L)", argument));
  28. return hookCallbackResult(pResult);
  29. }
  30. static SInt64 hookCallbackSubsecondTime(UInt64 pFunc, UInt64 argument)
  31. {
  32. SubsecondTime time(*(subsecond_time_t*)&argument);
  33. PyObject *pResult = HooksPy::callPythonFunction((PyObject *)pFunc, Py_BuildValue("(L)", time.getFS()));
  34. return hookCallbackResult(pResult);
  35. }
  36. static SInt64 hookCallbackString(UInt64 pFunc, UInt64 _argument)
  37. {
  38. const char* argument = (const char*)_argument;
  39. PyObject *pResult = HooksPy::callPythonFunction((PyObject *)pFunc, Py_BuildValue("(s)", argument));
  40. return hookCallbackResult(pResult);
  41. }
  42. static SInt64 hookCallbackMagicMarkerType(UInt64 pFunc, UInt64 _argument)
  43. {
  44. MagicServer::MagicMarkerType* argument = (MagicServer::MagicMarkerType*)_argument;
  45. PyObject *pResult = HooksPy::callPythonFunction((PyObject *)pFunc, Py_BuildValue("(iiKKs)", argument->thread_id, argument->core_id, argument->arg0, argument->arg1, argument->str));
  46. return hookCallbackResult(pResult);
  47. }
  48. static SInt64 hookCallbackThreadCreateType(UInt64 pFunc, UInt64 _argument)
  49. {
  50. HooksManager::ThreadCreate* argument = (HooksManager::ThreadCreate*)_argument;
  51. PyObject *pResult = HooksPy::callPythonFunction((PyObject *)pFunc, Py_BuildValue("(ii)", argument->thread_id, argument->creator_thread_id));
  52. return hookCallbackResult(pResult);
  53. }
  54. static SInt64 hookCallbackThreadTimeType(UInt64 pFunc, UInt64 _argument)
  55. {
  56. HooksManager::ThreadTime* argument = (HooksManager::ThreadTime*)_argument;
  57. SubsecondTime time(argument->time);
  58. PyObject *pResult = HooksPy::callPythonFunction((PyObject *)pFunc, Py_BuildValue("(iL)", argument->thread_id, time.getFS()));
  59. return hookCallbackResult(pResult);
  60. }
  61. static SInt64 hookCallbackThreadStallType(UInt64 pFunc, UInt64 _argument)
  62. {
  63. HooksManager::ThreadStall* argument = (HooksManager::ThreadStall*)_argument;
  64. SubsecondTime time(argument->time);
  65. PyObject *pResult = HooksPy::callPythonFunction((PyObject *)pFunc, Py_BuildValue("(isL)", argument->thread_id, ThreadManager::stall_type_names[argument->reason], time.getFS()));
  66. return hookCallbackResult(pResult);
  67. }
  68. static SInt64 hookCallbackThreadResumeType(UInt64 pFunc, UInt64 _argument)
  69. {
  70. HooksManager::ThreadResume* argument = (HooksManager::ThreadResume*)_argument;
  71. SubsecondTime time(argument->time);
  72. PyObject *pResult = HooksPy::callPythonFunction((PyObject *)pFunc, Py_BuildValue("(iiL)", argument->thread_id, argument->thread_by, time.getFS()));
  73. return hookCallbackResult(pResult);
  74. }
  75. static SInt64 hookCallbackThreadMigrateType(UInt64 pFunc, UInt64 _argument)
  76. {
  77. HooksManager::ThreadMigrate* argument = (HooksManager::ThreadMigrate*)_argument;
  78. SubsecondTime time(argument->time);
  79. PyObject *pResult = HooksPy::callPythonFunction((PyObject *)pFunc, Py_BuildValue("(iiL)", argument->thread_id, argument->core_id, time.getFS()));
  80. return hookCallbackResult(pResult);
  81. }
  82. static SInt64 hookCallbackSyscallEnter(UInt64 pFunc, UInt64 _argument)
  83. {
  84. SyscallMdl::HookSyscallEnter* argument = (SyscallMdl::HookSyscallEnter*)_argument;
  85. SubsecondTime time(argument->time);
  86. PyObject *pResult = HooksPy::callPythonFunction((PyObject *)pFunc, Py_BuildValue("(iiLi(llllll))", argument->thread_id, argument->core_id, time.getFS(),
  87. argument->syscall_number, argument->args.arg0, argument->args.arg1, argument->args.arg2, argument->args.arg3, argument->args.arg4, argument->args.arg5));
  88. return hookCallbackResult(pResult);
  89. }
  90. static SInt64 hookCallbackSyscallExit(UInt64 pFunc, UInt64 _argument)
  91. {
  92. SyscallMdl::HookSyscallExit* argument = (SyscallMdl::HookSyscallExit*)_argument;
  93. SubsecondTime time(argument->time);
  94. PyObject *pResult = HooksPy::callPythonFunction((PyObject *)pFunc, Py_BuildValue("(iiLiO)", argument->thread_id, argument->core_id, time.getFS(),
  95. argument->ret_val, argument->emulated ? Py_True : Py_False));
  96. return hookCallbackResult(pResult);
  97. }
  98. static PyObject *
  99. registerHook(PyObject *self, PyObject *args)
  100. {
  101. int hook = -1;
  102. PyObject *pFunc = NULL;
  103. if (!PyArg_ParseTuple(args, "lO", &hook, &pFunc))
  104. return NULL;
  105. if (hook < 0 || hook >= HookType::HOOK_TYPES_MAX) {
  106. PyErr_SetString(PyExc_ValueError, "Hook type out of range");
  107. return NULL;
  108. }
  109. if (!PyCallable_Check(pFunc)) {
  110. PyErr_SetString(PyExc_TypeError, "Second argument must be callable");
  111. return NULL;
  112. }
  113. Py_INCREF(pFunc);
  114. HookType::hook_type_t type = HookType::hook_type_t(hook);
  115. switch(type) {
  116. case HookType::HOOK_PERIODIC:
  117. Sim()->getHooksManager()->registerHook(type, hookCallbackSubsecondTime, (UInt64)pFunc);
  118. break;
  119. case HookType::HOOK_SIM_START:
  120. case HookType::HOOK_SIM_END:
  121. case HookType::HOOK_ROI_BEGIN:
  122. case HookType::HOOK_ROI_END:
  123. case HookType::HOOK_APPLICATION_ROI_BEGIN:
  124. case HookType::HOOK_APPLICATION_ROI_END:
  125. case HookType::HOOK_SIGUSR1:
  126. Sim()->getHooksManager()->registerHook(type, hookCallbackNone, (UInt64)pFunc);
  127. break;
  128. case HookType::HOOK_PERIODIC_INS:
  129. case HookType::HOOK_CPUFREQ_CHANGE:
  130. case HookType::HOOK_INSTR_COUNT:
  131. case HookType::HOOK_INSTRUMENT_MODE:
  132. case HookType::HOOK_APPLICATION_START:
  133. case HookType::HOOK_APPLICATION_EXIT:
  134. Sim()->getHooksManager()->registerHook(type, hookCallbackInt, (UInt64)pFunc);
  135. break;
  136. case HookType::HOOK_PRE_STAT_WRITE:
  137. Sim()->getHooksManager()->registerHook(type, hookCallbackString, (UInt64)pFunc);
  138. break;
  139. case HookType::HOOK_MAGIC_MARKER:
  140. case HookType::HOOK_MAGIC_USER:
  141. Sim()->getHooksManager()->registerHook(type, hookCallbackMagicMarkerType, (UInt64)pFunc);
  142. break;
  143. case HookType::HOOK_THREAD_CREATE:
  144. Sim()->getHooksManager()->registerHook(type, hookCallbackThreadCreateType, (UInt64)pFunc);
  145. break;
  146. case HookType::HOOK_THREAD_START:
  147. case HookType::HOOK_THREAD_EXIT:
  148. Sim()->getHooksManager()->registerHook(type, hookCallbackThreadTimeType, (UInt64)pFunc);
  149. break;
  150. case HookType::HOOK_THREAD_STALL:
  151. Sim()->getHooksManager()->registerHook(type, hookCallbackThreadStallType, (UInt64)pFunc);
  152. break;
  153. case HookType::HOOK_THREAD_RESUME:
  154. Sim()->getHooksManager()->registerHook(type, hookCallbackThreadResumeType, (UInt64)pFunc);
  155. break;
  156. case HookType::HOOK_THREAD_MIGRATE:
  157. Sim()->getHooksManager()->registerHook(type, hookCallbackThreadMigrateType, (UInt64)pFunc);
  158. break;
  159. case HookType::HOOK_SYSCALL_ENTER:
  160. Sim()->getHooksManager()->registerHook(type, hookCallbackSyscallEnter, (UInt64)pFunc);
  161. break;
  162. case HookType::HOOK_SYSCALL_EXIT:
  163. Sim()->getHooksManager()->registerHook(type, hookCallbackSyscallExit, (UInt64)pFunc);
  164. break;
  165. case HookType::HOOK_TYPES_MAX:
  166. assert(0);
  167. }
  168. Py_RETURN_NONE;
  169. }
  170. static PyObject *
  171. triggerHookMagicUser(PyObject *self, PyObject *args)
  172. {
  173. UInt64 a, b;
  174. if (!PyArg_ParseTuple(args, "ll", &a, &b))
  175. return NULL;
  176. UInt64 res = Sim()->getMagicServer()->Magic_unlocked(INVALID_THREAD_ID, INVALID_CORE_ID, SIM_CMD_USER, a, b);
  177. return PyInt_FromLong(res);
  178. }
  179. static PyMethodDef PyHooksMethods[] = {
  180. {"register", registerHook, METH_VARARGS, "Register callback function to a Sniper hook."},
  181. {"trigger_magic_user", triggerHookMagicUser, METH_VARARGS, "Trigger HOOK_MAGIC_USER hook."},
  182. {NULL, NULL, 0, NULL} /* Sentinel */
  183. };
  184. void HooksPy::PyHooks::setup()
  185. {
  186. PyObject *pModule = Py_InitModule("sim_hooks", PyHooksMethods);
  187. PyObject *pHooks = PyDict_New();
  188. PyObject_SetAttrString(pModule, "hooks", pHooks);
  189. for(int i = 0; i < int(HookType::HOOK_TYPES_MAX); ++i) {
  190. PyObject *pGlobalConst = PyInt_FromLong(i);
  191. PyObject_SetAttrString(pModule, HookType::hook_type_names[i], pGlobalConst);
  192. PyDict_SetItemString(pHooks, HookType::hook_type_names[i], pGlobalConst);
  193. Py_DECREF(pGlobalConst);
  194. }
  195. Py_DECREF(pHooks);
  196. }