memdbg.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import sys
  2. import traceback
  3. from cffi import api as _api
  4. sys.modules["ssl"] = None
  5. sys.modules["_hashlib"] = None
  6. _ffi = _api.FFI()
  7. _ffi.cdef(
  8. """
  9. void *malloc(size_t size);
  10. void free(void *ptr);
  11. void *realloc(void *ptr, size_t size);
  12. int CRYPTO_set_mem_functions(
  13. void *(*m)(size_t),void *(*r)(void *,size_t), void (*f)(void *));
  14. int backtrace(void **buffer, int size);
  15. char **backtrace_symbols(void *const *buffer, int size);
  16. void backtrace_symbols_fd(void *const *buffer, int size, int fd);
  17. """
  18. ) # noqa
  19. _api = _ffi.verify(
  20. """
  21. #include <openssl/crypto.h>
  22. #include <stdlib.h>
  23. #include <execinfo.h>
  24. """,
  25. libraries=["crypto"],
  26. )
  27. C = _ffi.dlopen(None)
  28. verbose = False
  29. def log(s):
  30. if verbose:
  31. print(s)
  32. def _backtrace():
  33. buf = _ffi.new("void*[]", 64)
  34. result = _api.backtrace(buf, len(buf))
  35. strings = _api.backtrace_symbols(buf, result)
  36. stack = [_ffi.string(strings[i]) for i in range(result)]
  37. C.free(strings)
  38. return stack
  39. @_ffi.callback("void*(*)(size_t)")
  40. def malloc(n):
  41. memory = C.malloc(n)
  42. python_stack = traceback.extract_stack(limit=3)
  43. c_stack = _backtrace()
  44. heap[memory] = [(n, python_stack, c_stack)]
  45. log("malloc(%d) -> %s" % (n, memory))
  46. return memory
  47. @_ffi.callback("void*(*)(void*, size_t)")
  48. def realloc(p, n):
  49. memory = C.realloc(p, n)
  50. old = heap.pop(p)
  51. python_stack = traceback.extract_stack(limit=3)
  52. c_stack = _backtrace()
  53. old.append((n, python_stack, c_stack))
  54. heap[memory] = old
  55. log("realloc(0x%x, %d) -> %s" % (int(_ffi.cast("int", p)), n, memory))
  56. return memory
  57. @_ffi.callback("void(*)(void*)")
  58. def free(p):
  59. if p != _ffi.NULL:
  60. C.free(p)
  61. del heap[p]
  62. log("free(0x%x)" % (int(_ffi.cast("int", p)),))
  63. if _api.CRYPTO_set_mem_functions(malloc, realloc, free):
  64. log("Enabled memory debugging")
  65. heap = {}
  66. else:
  67. log("Failed to enable memory debugging")
  68. heap = None