@@ -30,28 +30,15 @@ class MemoryState(Enum):
3030 MEM_RESERVE = 0x2000
3131 MEM_FREE = 0x10000
3232
33- class MemoryBasicInformation :
34- def __init__ (self , base : int , allocation_base : int , allocation_protect : MemoryProtect ):
35- self .base = base
36- self .allocation_base = allocation_base
37- self .allocation_protect = allocation_protect
38- self .region_size : int = PAGE_SIZE
39- self .state : MemoryState = None
40- self .protect : MemoryProtect = None
41- self .type : MemoryType = None
42-
43- def __str__ (self ):
44- return f"MemoryBasicInformation(base: { hex (self .base )} , allocation_base: { hex (self .allocation_base )} , region_size: { hex (self .region_size )} , state: { self .state } , protect: { self .protect } , type: { self .type } )"
45-
4633class MemoryRegion :
47- def __init__ (self , start : int , size : int , protect : MemoryProtect = MemoryProtect .PAGE_NOACCESS , type : MemoryType = MemoryType .MEM_PRIVATE , comment : str = "" ):
34+ def __init__ (self , start : int , size : int , protect : MemoryProtect = MemoryProtect .PAGE_NOACCESS , type : MemoryType = MemoryType .MEM_PRIVATE , info : Any = None ):
4835 assert start & 0xFFF == 0
4936 assert size & 0xFFF == 0
5037 self .start = start
5138 self .size = size
5239 self .protect = protect
5340 self .type = type
54- self .comment = comment
41+ self .info = info
5542
5643 @property
5744 def end (self ):
@@ -84,12 +71,12 @@ def overlaps(self, other):
8471
8572 def __str__ (self ):
8673 result = f"{ hex (self .start )} [{ hex (self .size )} ]"
87- if len ( self .comment ) > 0 :
88- result += f" ({ self .comment } )"
74+ if self .info is not None :
75+ result += f" ({ self .info } )"
8976 return result
9077
9178 def __repr__ (self ) -> str :
92- return f"MemoryRegion({ hex (self .start )} , { hex (self .size )} , { self .protect } , { self .type } , { self .comment } "
79+ return f"MemoryRegion({ hex (self .start )} , { hex (self .size )} , { self .protect } , { self .type } , { repr ( self .info ) } ) "
9380
9481 def pages (self ):
9582 for page in range (self .start , self .end , PAGE_SIZE ):
@@ -105,6 +92,20 @@ def decommit(self, addr: int, size: int) -> None:
10592 def protect (self , addr : int , size : int , protect : MemoryProtect ) -> None :
10693 raise NotImplementedError ()
10794
95+ class MemoryBasicInformation :
96+ def __init__ (self , base : int , allocation_base : int , allocation_protect : MemoryProtect ):
97+ self .base = base
98+ self .allocation_base = allocation_base
99+ self .allocation_protect = allocation_protect
100+ self .region_size : int = PAGE_SIZE
101+ self .state : MemoryState = None
102+ self .protect : MemoryProtect = None
103+ self .type : MemoryType = None
104+ self .info : Any = None
105+
106+ def __str__ (self ):
107+ return f"MemoryBasicInformation(base: { hex (self .base )} , allocation_base: { hex (self .allocation_base )} , region_size: { hex (self .region_size )} , state: { self .state } , protect: { self .protect } , type: { self .type } )"
108+
108109class MemoryManager :
109110 def __init__ (self , page_manager : PageManager , minimum = 0x10000 , maximum = 0x7fffffff0000 , granularity = 0x10000 ):
110111 self ._page_manager = page_manager
@@ -114,9 +115,9 @@ def __init__(self, page_manager: PageManager, minimum = 0x10000, maximum = 0x7ff
114115 self ._regions : List [MemoryRegion ] = []
115116 self ._committed : Dict [int , MemoryRegion ] = {}
116117
117- def find_parent (self , region : Union [MemoryRegion , int ]):
118+ def find_region (self , region : Union [MemoryRegion , int ]):
118119 if isinstance (region , int ):
119- region = MemoryRegion (self .page_align (region ), 0 )
120+ region = MemoryRegion (self .align_page (region ), 0 )
120121 index = bisect .bisect_right (self ._regions , region )
121122 if index == 0 :
122123 return None
@@ -127,31 +128,35 @@ def find_parent(self, region: Union[MemoryRegion, int]):
127128 else :
128129 return None
129130
130- def page_align (self , addr : int ):
131+ def find_commit (self , addr : int ):
132+ addr = self .align_page (addr )
133+ return self ._committed .get (addr , None )
134+
135+ def align_page (self , addr : int ):
131136 mask = PAGE_SIZE - 1
132137 return (addr + mask ) & ~ mask
133138
134- def allocation_align (self , addr : int ):
139+ def align_allocation (self , addr : int ):
135140 mask = self ._granularity - 1
136141 return (addr + mask ) & ~ mask
137142
138143 def find_free (self , size : int ):
139- assert size > 0 and self .page_align (size ) == size
144+ assert size > 0 and self .align_page (size ) == size
140145 base = self ._minimum
141146 while base < self ._maximum :
142147 info = self .query (base )
143148 assert info .base == base
144- if info .state == MemoryState .MEM_FREE and info .region_size >= size and self .allocation_align (base ) == base :
149+ if info .state == MemoryState .MEM_FREE and info .region_size >= size and self .align_allocation (base ) == base :
145150 return info .base
146151 base += info .region_size
147152 return None
148153
149- def reserve (self , start : int , size : int , protect : MemoryProtect , type : MemoryType = MemoryType .MEM_PRIVATE , comment : str = "" ):
154+ def reserve (self , start : int , size : int , protect : MemoryProtect , type : MemoryType = MemoryType .MEM_PRIVATE , info : Any = None ):
150155 assert isinstance (protect , MemoryProtect )
151156 assert isinstance (type , MemoryType )
152- assert size > 0 and self .page_align (size ) == size
153- assert self .allocation_align (start ) == start
154- region = MemoryRegion (start , size , protect , type , comment )
157+ assert size > 0 and self .align_page (size ) == size
158+ assert self .align_allocation (start ) == start
159+ region = MemoryRegion (start , size , protect , type , info )
155160 if region .start < self ._minimum or region .end > self ._maximum :
156161 raise KeyError (f"Requested region { region } is out of bounds" )
157162
@@ -170,9 +175,9 @@ def check_overlaps(index):
170175 self ._regions .insert (index , region )
171176
172177 def release (self , start : int ):
173- assert self .allocation_align (start ) == start
178+ assert self .align_allocation (start ) == start
174179
175- parent_region = self .find_parent (start )
180+ parent_region = self .find_region (start )
176181 if parent_region is None :
177182 raise KeyError (f"Could not find parent for { hex (start )} " )
178183 if parent_region .start != start :
@@ -191,10 +196,10 @@ def release(self, start: int):
191196
192197 def commit (self , start : int , size : int , protect : MemoryProtect = MemoryProtect .UNDEFINED ):
193198 assert isinstance (protect , MemoryProtect )
194- assert size > 0 and self .page_align (size ) == size
195- assert self .page_align (start ) == start
199+ assert size > 0 and self .align_page (size ) == size
200+ assert self .align_page (start ) == start
196201 region = MemoryRegion (start , size )
197- parent_region = self .find_parent (region )
202+ parent_region = self .find_region (region )
198203 if parent_region is None :
199204 raise KeyError (f"Could not find parent for { region } " )
200205
@@ -208,17 +213,19 @@ def commit(self, start: int, size: int, protect: MemoryProtect = MemoryProtect.U
208213 else :
209214 for page in region .pages ():
210215 if page in self ._committed :
211- self ._page_manager .protect (page , PAGE_SIZE , protect )
212- self ._committed [page ].protect = protect
216+ page_region = self ._committed [page ]
217+ if page_region .protect != protect :
218+ self ._page_manager .protect (page , PAGE_SIZE , protect )
219+ page_region .protect = protect
213220 else :
214221 self ._page_manager .commit (page , PAGE_SIZE , protect )
215222 self ._committed [page ] = MemoryRegion (page , PAGE_SIZE , protect , parent_region .type )
216223
217224 def decommit (self , start : int , size : int ):
218- assert size > 0 and self .page_align (size ) == size
219- assert self .page_align (start ) == start
225+ assert size > 0 and self .align_page (size ) == size
226+ assert self .align_page (start ) == start
220227 region = MemoryRegion (start , size )
221- parent_region = self .find_parent (region )
228+ parent_region = self .find_region (region )
222229 if parent_region is None :
223230 raise KeyError (f"Could not find parent for { region } " )
224231
@@ -234,10 +241,10 @@ def decommit(self, start: int, size: int):
234241
235242 def protect (self , start : int , size : int , protect : MemoryProtect ):
236243 assert isinstance (protect , MemoryProtect )
237- assert size > 0 and self .page_align (size ) == size
238- assert self .page_align (start ) == start
244+ assert size > 0 and self .align_page (size ) == size
245+ assert self .align_page (start ) == start
239246 region = MemoryRegion (start , size )
240- parent_region = self .find_parent (region )
247+ parent_region = self .find_region (region )
241248 if parent_region is None :
242249 raise KeyError (f"Could not find parent for { region } " )
243250
@@ -250,15 +257,17 @@ def protect(self, start: int, size: int, protect: MemoryProtect):
250257 old_protect = self ._committed [region .start ].protect
251258 self ._page_manager .protect (region .start , region .size , protect )
252259 for page in region .pages ():
253- self ._committed [page ].protect = protect
260+ page_region = self ._committed [page ]
261+ if page_region .protect != protect :
262+ page_region .protect = protect
254263
255264 return old_protect
256265
257266 def query (self , start : int ):
258- assert self .page_align (start ) == start
267+ start = self .align_page (start )
259268
260269 region = MemoryRegion (start , 0 )
261- parent_region = self .find_parent (region )
270+ parent_region = self .find_region (region )
262271 if parent_region is None :
263272 index = bisect .bisect_right (self ._regions , region )
264273 next_start = self ._maximum
@@ -279,11 +288,15 @@ def query(self, start: int):
279288 continue
280289 elif result is None :
281290 result = MemoryBasicInformation (page , parent_region .start , parent_region .protect )
291+ if page == parent_region .start :
292+ result .info = parent_region .info
282293 if page in self ._committed :
283294 result .state = MemoryState .MEM_COMMIT
284295 commited_page = self ._committed [page ]
285296 result .protect = commited_page .protect
286297 result .type = commited_page .type
298+ if commited_page .info :
299+ result .info = commited_page .info
287300 assert commited_page .type == parent_region .type
288301 else :
289302 result .state = MemoryState .MEM_RESERVE
@@ -292,6 +305,8 @@ def query(self, start: int):
292305 else :
293306 commited_page = self ._committed .get (page , None )
294307 if result .state == MemoryState .MEM_RESERVE :
308+ if commited_page is not None :
309+ break
295310 result .region_size += PAGE_SIZE
296311 elif result .state == MemoryState .MEM_COMMIT :
297312 if commited_page is not None and commited_page .type == result .type and commited_page .protect == result .protect :
@@ -301,3 +316,12 @@ def query(self, start: int):
301316 else :
302317 assert False # unreachable
303318 return result
319+
320+ def map (self ):
321+ addr = self ._minimum
322+ regions : List [MemoryBasicInformation ] = []
323+ while addr < self ._maximum :
324+ info = self .query (addr )
325+ regions .append (info )
326+ addr += info .region_size
327+ return regions
0 commit comments