ATLAS Offline Software
Loading...
Searching...
No Matches
sheap.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2#
3# File: GdbUtils/python/sheap.py
4# Created: A while ago, sss
5# Purpose: Dump out malloc heap regions.
6#
7
8import gdb
9
10def sheap_read_word (inf, addr):
11 mv = inf.read_memory (addr, 8)
12 return mv.cast('L')[0]
13
14def sheap_looks_free (inf, addr):
15 head = sheap_read_word (inf, addr+8)
16 if head > 128*1024*1024 or head < 8: return False
17 #print (hex(addr), hex(head))
18 head = head & ~1
19 if head & 2: return False
20 foot = sheap_read_word (inf, addr+head)
21 if head != foot: return False
22 nexthead = sheap_read_word (inf, addr+head+8)
23 if nexthead & 1: return False
24 #print ('found', hex(addr), hex(head), hex(foot), hex(nexthead))
25 return True
26
27def sheap_scan_2 (inf, addr):
28 head = sheap_read_word (inf, addr+8)
29 if head > 128*1024*1024 or head < 8:
30 return addr+8, False
31 head = head & ~1
32 if head & 2:
33 return addr+8, False
34 nexthead = sheap_read_word (inf, addr+head+8)
35 if nexthead & 1:
36 type = ' USED '
37 else:
38 if not sheap_looks_free (inf, addr):
39 return addr+8, False
40 type = ' FREE '
41 #print('sheap_scan_2' ,hex(addr), hex(head), hex(nexthead), type)
42 s = f'{int(addr):016x}:{type}{int(head):08x}\n'
43 gdb.write (s)
44 return addr+head, True
45
46def sheap_scan_1 (addr1, addr2, forced):
47 inf = gdb.selected_inferior()
48 addr1 = (addr1 + 7) & ~7 # Align
49 if not forced:
50 while addr1 < addr2 and not sheap_looks_free (inf, addr1):
51 addr1 += 8
52 while addr1 < addr2:
53 addr1, ok = sheap_scan_2 (inf, addr1)
54 if not ok: break
55 return addr1
56
57def sheap_scan (addr1, addr2, forced):
58 addr1 -= 8
59 while addr1 < addr2:
60 addr1 = sheap_scan_1 (addr1, addr2, forced)
61 forced = False
62 gdb.flush()
63 return
64
65
66def sheap (arg, forced):
67 args = arg.split()
68 if not args:
69 raise gdb.GdbError ('Missing start address')
70 start_arg = gdb.parse_and_eval (args[0])
71 end_arg = gdb.parse_and_eval (args[1]) if len(args) > 1 else start_arg + 1024
72 return sheap_scan (start_arg, end_arg, forced)
73
74
75class SHeap (gdb.Command):
76 """Dump out malloc heap in a range of addresses, showed allocated/free blocks.
77
78 sheap START-ADDR [END-ADDR]
79 will dump out free and allocated malloc blocks within the given address
80 range. If not given, END-ADDR is taken to be 1024 bytes after START-ADDR.
81
82 Caveats: It is not possible to reliably identify allocated memory blocks.
83 Dumping will start at the first free block found within
84 the given range, if any.
85
86 This only works with the GNU libc malloc, not with any
87 alternative allocators (tcmalloc, etc).
88 """
89 def __init__ (self):
90 super (SHeap, self).__init__ ("sheap", gdb.COMMAND_DATA)
91 return
92
93 def invoke (self, arg, from_tty):
94 return sheap (arg, False)
95
96
97SHeap()
invoke(self, arg, from_tty)
Definition sheap.py:93
sheap_scan_2(inf, addr)
Definition sheap.py:27
sheap_read_word(inf, addr)
Definition sheap.py:10
sheap_looks_free(inf, addr)
Definition sheap.py:14
sheap_scan_1(addr1, addr2, forced)
Definition sheap.py:46
sheap_scan(addr1, addr2, forced)
Definition sheap.py:57