memdbg.py 1.9 KB

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