proj/test-memory: Output well-formatted report
This commit is contained in:
@@ -54,71 +54,80 @@ SKIP_ERRORS: list[str] = ['EINTR']
|
||||
|
||||
|
||||
class MemoryAllocationParser(Parser):
|
||||
allocated: dict[int, tuple[str, str, str, int, int]]
|
||||
allocated: dict[int, tuple[str, int, str, str, int, str, int]]
|
||||
invalid_frees: list[tuple[str, int, str, str, int, str, int]]
|
||||
max_allocated: int
|
||||
num_alloc: int
|
||||
num_realloc: int
|
||||
num_free: int
|
||||
num_invalid_free: int
|
||||
|
||||
def before(self):
|
||||
self.allocated = {}
|
||||
self.invalid_frees = []
|
||||
self.max_allocated = 0
|
||||
self.num_alloc = 0
|
||||
self.num_realloc = 0
|
||||
self.num_free = 0
|
||||
self.num_invalid_free = 0
|
||||
|
||||
def after(self):
|
||||
if len(self.allocated) > 0:
|
||||
print("\x1B[31;1mNot free'd:\x1B[0m", file=sys.stderr)
|
||||
for ptr, (func, fname, sname, ret, size) in self.allocated.items():
|
||||
print(f'\x1B[31;1m 0x{ptr:x}: {size} bytes ({func}, return address {fname}+0x{ret:x} {sname})\x1B[0m', file=sys.stderr)
|
||||
else:
|
||||
print("\x1B[32;1mAll blocks free'd!\x1B[0m", file=sys.stderr)
|
||||
print(f'Max allocated: {self.max_allocated} bytes', file=sys.stderr)
|
||||
|
||||
def update_max_allocated(self):
|
||||
total = sum(a[-1] for a in self.allocated.values())
|
||||
total = sum(a[1] for a in self.allocated.values())
|
||||
if total > self.max_allocated:
|
||||
self.max_allocated = total
|
||||
|
||||
def after_malloc(self, size, ret_value, errno=None) -> None:
|
||||
self.num_alloc += 1
|
||||
if ret_value != 0:
|
||||
self.allocated[ret_value] = ('malloc', self.dli_file_name, self.dli_sym_name, self.rel_ret_addr, size)
|
||||
self.update_max_allocated()
|
||||
self.allocated[ret_value] = ('malloc', size,
|
||||
self.dli_file_name, self.dli_sym_name, self.rel_ret_addr,
|
||||
self.src_file_name, self.src_line_num)
|
||||
self.update_max_allocated()
|
||||
|
||||
def after_calloc(self, nmemb, size, ret_value, errno=None) -> None:
|
||||
self.num_alloc += 1
|
||||
if ret_value != 0:
|
||||
self.allocated[ret_value] = ('calloc', self.dli_file_name, self.dli_sym_name, self.rel_ret_addr, nmemb * size)
|
||||
self.update_max_allocated()
|
||||
self.allocated[ret_value] = ('calloc', nmemb * size,
|
||||
self.dli_file_name, self.dli_sym_name, self.rel_ret_addr,
|
||||
self.src_file_name, self.src_line_num)
|
||||
self.update_max_allocated()
|
||||
|
||||
def after_realloc(self, ptr, size, ret_value, errno=None) -> None:
|
||||
self.num_realloc += 1
|
||||
if ptr != 0:
|
||||
if ptr == 0:
|
||||
self.num_alloc += 1
|
||||
if ret_value != 0:
|
||||
self.allocated[ret_value] = ('realloc', size,
|
||||
self.dli_file_name, self.dli_sym_name, self.rel_ret_addr,
|
||||
self.src_file_name, self.src_line_num)
|
||||
else:
|
||||
self.num_realloc += 1
|
||||
if ret_value != 0 and ptr in self.allocated:
|
||||
v = self.allocated[ptr]
|
||||
del self.allocated[ptr]
|
||||
self.allocated[ret_value] = (v[0], v[1], v[2], v[3], size)
|
||||
self.update_max_allocated()
|
||||
self.allocated[ret_value] = (v[0], size, v[2], v[3], v[4], v[5], v[6])
|
||||
self.update_max_allocated()
|
||||
|
||||
def after_reallocarray(self, ptr, nmemb, size, ret_value, errno=None) -> None:
|
||||
self.num_realloc += 1
|
||||
if ptr != 0:
|
||||
if ptr == 0:
|
||||
self.num_alloc += 1
|
||||
if ret_value != 0:
|
||||
self.allocated[ret_value] = ('reallocarray', nmemb * size,
|
||||
self.dli_file_name, self.dli_sym_name, self.rel_ret_addr,
|
||||
self.src_file_name, self.src_line_num)
|
||||
else:
|
||||
self.num_realloc += 1
|
||||
if ret_value != 0:
|
||||
v = self.allocated[ptr]
|
||||
del self.allocated[ptr]
|
||||
self.allocated[ret_value] = (v[0], v[1], v[2], v[3], nmemb * size)
|
||||
self.update_max_allocated()
|
||||
self.allocated[ret_value] = (v[0], nmemb * size, v[2], v[3], v[4], v[5], v[6])
|
||||
self.update_max_allocated()
|
||||
|
||||
def after_getaddrinfo(self, node, service, hints, res_ptr, ret_value, errno=None, res=None) -> None:
|
||||
self.num_alloc += 1
|
||||
if ret_value[0] == 0 and res is not None:
|
||||
size = sum(48 + r['ai_addrlen'] for r in res[1])
|
||||
self.allocated[res[0]] = ('getaddrinfo', self.dli_file_name, self.dli_sym_name, self.rel_ret_addr, size)
|
||||
self.update_max_allocated()
|
||||
self.allocated[res[0]] = ('getaddrinfo', size,
|
||||
self.dli_file_name, self.dli_sym_name, self.rel_ret_addr,
|
||||
self.src_file_name, self.src_line_num)
|
||||
self.update_max_allocated()
|
||||
|
||||
def after_free(self, ptr) -> None:
|
||||
self.num_free += 1
|
||||
@@ -127,7 +136,9 @@ class MemoryAllocationParser(Parser):
|
||||
del self.allocated[ptr]
|
||||
else:
|
||||
self.num_free -= 1
|
||||
self.num_invalid_free += 1
|
||||
self.invalid_frees.append(('free', ptr,
|
||||
self.dli_file_name, self.dli_sym_name, self.rel_ret_addr,
|
||||
self.src_file_name, self.src_line_num))
|
||||
|
||||
def after_freeaddrinfo(self, res: Pointer) -> None:
|
||||
self.num_free += 1
|
||||
@@ -136,7 +147,9 @@ class MemoryAllocationParser(Parser):
|
||||
del self.allocated[res]
|
||||
else:
|
||||
self.num_free -= 1
|
||||
self.num_invalid_free += 1
|
||||
self.invalid_frees.append(('freeaddrinfo', res,
|
||||
self.dli_file_name, self.dli_sym_name, self.rel_ret_addr,
|
||||
self.src_file_name, self.src_line_num))
|
||||
|
||||
|
||||
class MemoryAllocationTester(MemoryAllocationParser, Handler):
|
||||
|
||||
Reference in New Issue
Block a user