Skip to content

Commit 9868cf9

Browse files
committed
my own kitchen sing commit
Signed-off-by: Vlastimil Babka <[email protected]>
1 parent a4a6d81 commit 9868cf9

File tree

5 files changed

+95
-15
lines changed

5 files changed

+95
-15
lines changed

crash/types/list.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,21 @@
1111
long = int
1212

1313
list_head_type = gdb.lookup_type("struct list_head")
14-
def list_for_each(list_head):
14+
def list_for_each(list_head, reverse=False):
1515
if list_head.type == list_head_type.pointer():
1616
list_head = list_head.dereference()
1717
elif list_head.type != list_head_type:
1818
raise gdb.GdbError("Must be struct list_head not %s" % list_head.type)
1919

2020
fast = None
21+
next_ = 'next'
22+
prev_ = 'prev'
23+
if reverse:
24+
next_ = 'prev'
25+
prev_ = 'next'
2126

2227
try:
23-
nxt = list_head['next']
28+
nxt = list_head[next_]
2429
prev = list_head
2530
node = nxt.dereference()
2631
except gdb.error as e:
@@ -31,20 +36,20 @@ def list_for_each(list_head):
3136
yield node.address
3237

3338
try:
34-
if long(prev.address) != long(node['prev']):
35-
print(("broken prev link %x -next-> %x -prev-> %x" %
36-
(prev.address, node.address, long(node['prev']))))
39+
if long(prev.address) != long(node[prev_]):
40+
print(("broken %s link %x -%s-> %x -%s-> %x" %
41+
(prev_, prev.address, next_, node.address, prev_, long(node[prev_]))))
3742
# broken prev link means there might be a cycle that does not
3843
# include the initial head, so start detecting cycles
3944
fast = node
40-
nxt = node['next']
45+
nxt = node[next_]
4146

4247
if fast is not None:
4348
# are we detecting cycles? advance fast 2 times and compare
4449
# each with our current node (Floyd's Tortoise and Hare
4550
# algorithm)
4651
for i in range(2):
47-
fast = fast['next'].dereference()
52+
fast = fast[next_].dereference()
4853
if node.address == fast.address:
4954
print("detected linked list cycle, aborting traversal")
5055
return

crash/types/node.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,12 @@ def from_nid(nid):
5959
def for_each_zone(self):
6060
node_zones = self.gdb_obj["node_zones"]
6161
(first, last) = node_zones.type.range()
62+
node_zones = long(node_zones.address)
63+
zone_type = gdb.lookup_type("struct zone")
6264
for zid in range(first, last + 1):
63-
yield crash.types.zone.Zone(node_zones[zid], zid)
65+
z = crash.types.util.addr_cast(node_zones + zid * zone_type.sizeof,
66+
zone_type)
67+
yield crash.types.zone.Zone(z, zid)
6468

6569
def __init__(self, obj):
6670
self.gdb_obj = obj

crash/types/page.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
33

44
from __future__ import print_function
5+
import random
56

67
import gdb
78
from .util import container_of, find_member_variant
@@ -19,6 +20,8 @@
1920
struct_page_type = gdb.lookup_type('struct page')
2021

2122
vmemmap = gdb.Value(VMEMMAP_START).cast(struct_page_type.pointer())
23+
# TODO works only on x86?
24+
max_pfn = long(gdb.lookup_global_symbol("max_pfn").value())
2225

2326
def get_flag(flagname):
2427
sym = gdb.lookup_symbol("PG_" + flagname, None)[0]
@@ -30,6 +33,10 @@ def get_flag(flagname):
3033
PG_tail = get_flag("tail")
3134
PG_slab = get_flag("slab")
3235

36+
NR_FLAGS = long(gdb.lookup_symbol("__NR_PAGEFLAGS", None)[0].value())
37+
38+
pageflags_type = gdb.lookup_type("enum pageflags")
39+
3340
#TODO debuginfo won't tell us, depends on version?
3441
PAGE_MAPPING_ANON = 1
3542

@@ -60,15 +67,22 @@ def from_obj(gdb_obj):
6067

6168
@staticmethod
6269
def for_each():
63-
# TODO works only on x86?
64-
max_pfn = long(gdb.lookup_global_symbol("max_pfn").value())
6570
for pfn in range(max_pfn):
6671
try:
6772
yield Page.from_pfn(pfn)
6873
except gdb.error as e:
6974
# TODO: distinguish pfn_valid() and report failures for those?
7075
pass
7176

77+
@staticmethod
78+
def for_random(count):
79+
for pfn in random.sample(xrange(max_pfn), count):
80+
try:
81+
yield Page.from_pfn(pfn)
82+
except gdb.error as e:
83+
# TODO: distinguish pfn_valid() and report failures for those?
84+
pass
85+
7286
def is_tail(self):
7387
if PG_tail is not None:
7488
return bool(self.flags & PG_tail)
@@ -82,6 +96,27 @@ def is_anon(self):
8296
mapping = long(self.gdb_obj["mapping"])
8397
return (mapping & PAGE_MAPPING_ANON) != 0
8498

99+
def is_buddy(self):
100+
return int(self.gdb_obj["_mapcount"]["counter"]) == int(-128L)
101+
102+
def is_buddy_tail(self):
103+
if self.get_count() != 0:
104+
return False
105+
106+
# todo unhardcode
107+
for pfn in range(self.pfn, max(self.pfn - 1024, 0) -1):
108+
p = Page.from_pfn(pfn)
109+
110+
if p.is_buddy():
111+
order = long(p.gdb_obj["private"])
112+
return self.pfn < p.pfn + 1 << order
113+
114+
if p.get_count() != 0:
115+
return False
116+
117+
def get_count(self):
118+
return int(self.compound_head().gdb_obj["_count"]["counter"])
119+
85120
def get_slab_cache(self):
86121
if Page.slab_cache_name == "lru":
87122
return self.gdb_obj["lru"]["next"]
@@ -96,6 +131,18 @@ def get_nid(self):
96131
# TODO unhardcode
97132
return self.flags >> (64 - NODES_SHIFT)
98133

134+
def get_flags(self):
135+
return self.flags & ((1 << NR_FLAGS) - 1)
136+
137+
def print_flags(self):
138+
flags = self.get_flags()
139+
print ("%x" % flags)
140+
for field in pageflags_type.fields():
141+
if field.name == "__NR_PAGEFLAGS":
142+
break
143+
if self.flags & (1 << field.enumval):
144+
print(field.name)
145+
99146
def compound_head(self):
100147
if not self.is_tail():
101148
return self

crash/types/slab.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343

4444
BUFCTL_END = ~0 & 0xffffffff
4545

46+
slab_pages = set()
47+
4648
class Slab:
4749
@staticmethod
4850
def from_addr(slab_addr, kmem_cache):
@@ -199,13 +201,15 @@ def check(self, slabtype, nid):
199201
page = Page.from_addr(obj).compound_head()
200202
except:
201203
self.__error(": failed to get page for object %x" % obj)
202-
continue
204+
break
203205

204206
if long(page.gdb_obj.address) == last_page_addr:
205207
continue
206208

207209
last_page_addr = long(page.gdb_obj.address)
208210

211+
slab_pages.add(last_page_addr)
212+
209213
if page.get_nid() != nid:
210214
self.__error(": obj %x is on nid %d instead of %d" %
211215
(obj, page.get_nid(), nid))
@@ -223,6 +227,16 @@ def check(self, slabtype, nid):
223227
if slab_addr != self.gdb_obj.address:
224228
self.__error(": obj %x is on page where pointer to slab wrongly points to %x" %
225229
(obj, slab_addr))
230+
231+
slab_addr = self.s_mem - long(self.gdb_obj["colouroff"])
232+
order = long(self.kmem_cache.gdb_obj["gfporder"])
233+
for i in range(1 << order):
234+
try:
235+
page = Page.from_addr(slab_addr)
236+
slab_addr += 4096
237+
slab_pages.add(long(page.gdb_obj.address))
238+
except:
239+
pass
226240
return num_free
227241

228242
def __init__(self, gdb_obj, kmem_cache):
@@ -410,4 +424,14 @@ def check_all(self):
410424
if free_declared != free_counted:
411425
print(("free objects mismatch on node %d: declared=%d counted=%d" %
412426
(nid, free_declared, free_counted)))
413-
427+
for ac_obj in self.get_array_caches().keys():
428+
slab = Slab.from_obj(ac_obj)
429+
if not slab:
430+
print("WARNING: object in array_cache not on slab")
431+
continue
432+
if slab.kmem_cache != self:
433+
print("WARNING: cache mismatch")
434+
continue
435+
436+
437+

crash/types/task.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ def __init__(self, task_struct, active = False,
4848
if cpu is not None and not isinstance(cpu, int):
4949
raise TypeError("cpu must be integer or None")
5050

51-
if not isinstance(task_struct, gdb.Value) or \
52-
not task_struct.type != self.task_struct_type:
53-
raise TypeError("task_struct must be gdb.Value describing struct task_struct")
51+
# if not isinstance(task_struct, gdb.Value) or \
52+
# not task_struct.type != self.task_struct_type:
53+
# raise TypeError("task_struct must be gdb.Value describing struct task_struct")
5454

5555
self.task_struct = task_struct
5656
self.active = active

0 commit comments

Comments
 (0)