1010
1111class R2Mem (QlMemoryManager ):
1212 '''A wrapper for QlMemoryManager that uses map_ptr and store raw memory in map_info
13- NOTE: ql.mem already contains map_infor after loader.run(), so instead of super().__init__(),
13+ NOTE: ql.mem already contains map_info after loader.run(), so instead of super().__init__(),
1414 we accept mem object to simulate inheritance by composition
1515 '''
1616
@@ -43,14 +43,12 @@ def map(self, addr: int, size: int, perms: int = UC_PROT_ALL, info: Optional[str
4343 """
4444
4545 assert perms & ~ UC_PROT_ALL == 0 , f'unexpected permissions mask { perms } '
46-
46+
4747 if not self .is_available (addr , size ):
48- for line in self .get_formatted_mapinfo ():
49- print (line )
5048 raise QlMemoryMappedError (f'Requested memory { addr :#x} + { size :#x} is unavailable' )
5149
52- buf = self .map_ptr (addr , size , perms , ptr )
53- self .add_mapinfo (addr , addr + size , perms , info or '[mapped]' , is_mmio = False , data = buf )
50+ self .map_ptr (addr , size , perms , ptr )
51+ self .add_mapinfo (addr , addr + size , perms , info or '[mapped]' , is_mmio = False )
5452
5553 def map_ptr (self , addr : int , size : int , perms : int = UC_PROT_ALL , buf : Optional [bytearray ] = None ) -> bytearray :
5654 """Map a new memory range allocated as Python bytearray, will not affect map_info
@@ -67,123 +65,6 @@ def map_ptr(self, addr: int, size: int, perms: int = UC_PROT_ALL, buf: Optional[
6765 buf = buf or bytearray (size )
6866 buf_type = ctypes .c_ubyte * size
6967 cdata = buf_type .from_buffer (buf )
70- self .cmap [addr ] = cdata
68+ self .cmap [addr ] = cdata # NOTE: will memory leak or invalid reference happen if not updated when splitting memory?
7169 self .ql .uc .mem_map_ptr (addr , size , perms , cdata )
7270 return buf
73-
74- def add_mapinfo (self , mem_s : int , mem_e : int , mem_p : int , mem_info : str , is_mmio : bool = False , data : bytearray = None ):
75- """Add a new memory range to map.
76-
77- Args:
78- mem_s: memory range start
79- mem_e: memory range end
80- mem_p: permissions mask
81- mem_info: map entry label
82- is_mmio: memory range is mmio
83- """
84- self .map_info .append ((mem_s , mem_e , mem_p , mem_info , is_mmio , data ))
85- self .map_info .sort (key = lambda tp : tp [0 ])
86-
87- def del_mapinfo (self , mem_s : int , mem_e : int ):
88- """Subtract a memory range from map, will destroy data and unmap uc mem in the range.
89-
90- Args:
91- mem_s: memory range start
92- mem_e: memory range end
93- """
94-
95- tmp_map_info : MutableSequence [MapInfoEntry ] = []
96-
97- for s , e , p , info , mmio , data in self .map_info :
98- if e <= mem_s :
99- tmp_map_info .append ((s , e , p , info , mmio , data ))
100- continue
101-
102- if s >= mem_e :
103- tmp_map_info .append ((s , e , p , info , mmio , data ))
104- continue
105-
106- del self .cmap [s ] # remove cdata reference starting at s
107- if s < mem_s :
108- self .ql .uc .mem_unmap (s , mem_s - s )
109- self .map_ptr (s , mem_s - s , p , data [:mem_s - s ])
110- tmp_map_info .append ((s , mem_s , p , info , mmio , data [:mem_s - s ]))
111-
112- if s == mem_s :
113- pass
114-
115- if e > mem_e :
116- self .ql .uc .mem_unmap (mem_e , e - mem_e )
117- self .map_ptr (mem_e , e - mem_e , p , data [mem_e - e :])
118- tmp_map_info .append ((mem_e , e , p , info , mmio , data [mem_e - e :]))
119-
120- if e == mem_e :
121- pass
122-
123- del data [mem_s - s :mem_e - s ]
124-
125- self .map_info = tmp_map_info
126-
127- def change_mapinfo (self , mem_s : int , mem_e : int , mem_p : Optional [int ] = None , mem_info : Optional [str ] = None , data : Optional [bytearray ] = None ):
128- tmp_map_info : Optional [MapInfoEntry ] = None
129- info_idx : int = None
130-
131- for idx , map_info in enumerate (self .map_info ):
132- if mem_s >= map_info [0 ] and mem_e <= map_info [1 ]:
133- tmp_map_info = map_info
134- info_idx = idx
135- break
136-
137- if tmp_map_info is None :
138- self .ql .log .error (f'Cannot change mapinfo at { mem_s :#08x} -{ mem_e :#08x} ' )
139- return
140-
141- if mem_p is not None :
142- data = data or self .read (mem_s , mem_e - mem_s ).copy ()
143- assert (len (data ) == mem_e - mem_s )
144- self .unmap (mem_s , mem_e - mem_s )
145- self .map_ptr (mem_s , mem_e - mem_s , mem_p , data )
146- self .add_mapinfo (mem_s , mem_e , mem_p , mem_info or tmp_map_info [3 ], tmp_map_info [4 ], data )
147- return
148-
149- if mem_info is not None :
150- self .map_info [info_idx ] = (tmp_map_info [0 ], tmp_map_info [1 ], tmp_map_info [2 ], mem_info , tmp_map_info [4 ], tmp_map_info [5 ])
151-
152- def save (self ):
153- """Save entire memory content.
154- """
155-
156- mem_dict = {
157- "ram" : [],
158- "mmio" : []
159- }
160-
161- for lbound , ubound , perm , label , is_mmio , data in self .map_info :
162- if is_mmio :
163- mem_dict ['mmio' ].append ((lbound , ubound , perm , label , * self .mmio_cbs [(lbound , ubound )]))
164- else :
165- data = self .read (lbound , ubound - lbound ) # read instead of using data from map_info to avoid error
166- mem_dict ['ram' ].append ((lbound , ubound , perm , label , data ))
167-
168- return mem_dict
169-
170- def restore (self , mem_dict ):
171- """Restore saved memory content.
172- """
173-
174- for lbound , ubound , perms , label , data in mem_dict ['ram' ]:
175- self .ql .log .debug (f'restoring memory range: { lbound :#08x} { ubound :#08x} { label } ' )
176-
177- size = ubound - lbound
178- if self .is_available (lbound , size ):
179- self .ql .log .debug (f'mapping { lbound :#08x} { ubound :#08x} , mapsize = { size :#x} ' )
180- self .map (lbound , size , perms , label , data )
181-
182- self .ql .log .debug (f'writing { len (data ):#x} bytes at { lbound :#08x} ' )
183- self .write (lbound , bytes (data ))
184-
185- for lbound , ubound , perms , label , read_cb , write_cb in mem_dict ['mmio' ]:
186- self .ql .log .debug (f"restoring mmio range: { lbound :#08x} { ubound :#08x} { label } " )
187-
188- #TODO: Handle overlapped MMIO?
189- self .map_mmio (lbound , ubound - lbound , read_cb , write_cb , info = label )
0 commit comments