22# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
33
44from __future__ import print_function
5+ import random
56
67import gdb
78from .util import container_of , find_member_variant
1920struct_page_type = gdb .lookup_type ('struct page' )
2021
2122vmemmap = 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
2326def get_flag (flagname ):
2427 sym = gdb .lookup_symbol ("PG_" + flagname , None )[0 ]
@@ -30,6 +33,10 @@ def get_flag(flagname):
3033PG_tail = get_flag ("tail" )
3134PG_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?
3441PAGE_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
0 commit comments