Skip to content

Commit c13b6ca

Browse files
committed
Additional cleanup and tidy-up
1 parent 50fc1b2 commit c13b6ca

File tree

1 file changed

+69
-60
lines changed

1 file changed

+69
-60
lines changed

qiling/os/memory.py

Lines changed: 69 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,15 @@
66
import os, re
77
from typing import Any, List, MutableSequence, Optional, Sequence, Tuple
88

9+
from unicorn import UC_PROT_NONE, UC_PROT_READ, UC_PROT_WRITE, UC_PROT_EXEC, UC_PROT_ALL
10+
911
from qiling import Qiling
1012
from qiling.const import *
1113
from qiling.exception import *
1214

1315
# tuple: range start, range end, permissions mask, range label
1416
MapInfoEntry = Tuple[int, int, int, str]
1517

16-
from unicorn import (
17-
UC_PROT_ALL,
18-
UC_PROT_EXEC,
19-
UC_PROT_NONE,
20-
UC_PROT_READ,
21-
UC_PROT_WRITE,
22-
)
23-
2418
class QlMemoryManager:
2519
"""
2620
some ideas and code from:
@@ -79,43 +73,56 @@ def string(self, addr: int, value=None, encoding='utf-8') -> Optional[str]:
7973
self.__write_string(addr, value, encoding)
8074

8175
def add_mapinfo(self, mem_s: int, mem_e: int, mem_p: int, mem_info: str):
82-
tmp_map_info = []
76+
"""Add a new memory range to map.
77+
78+
Args:
79+
mem_s: memory range start
80+
mem_e: memory range end
81+
mem_p: permissions mask
82+
mem_info: map entry label
83+
"""
84+
85+
tmp_map_info: MutableSequence[MapInfoEntry] = []
8386
insert_flag = 0
8487
map_info = self.map_info
88+
8589
if len(map_info) == 0:
86-
tmp_map_info.append([mem_s, mem_e, mem_p, mem_info])
90+
tmp_map_info.append((mem_s, mem_e, mem_p, mem_info))
8791
else:
8892
for s, e, p, info in map_info:
8993
if e <= mem_s:
90-
tmp_map_info.append([s, e, p, info])
94+
tmp_map_info.append((s, e, p, info))
9195
continue
96+
9297
if s >= mem_e:
9398
if insert_flag == 0:
9499
insert_flag = 1
95-
tmp_map_info.append([mem_s, mem_e, mem_p, mem_info])
96-
tmp_map_info.append([s, e, p, info])
100+
tmp_map_info.append((mem_s, mem_e, mem_p, mem_info))
101+
102+
tmp_map_info.append((s, e, p, info))
97103
continue
104+
98105
if s < mem_s:
99-
tmp_map_info.append([s, mem_s, p, info])
106+
tmp_map_info.append((s, mem_s, p, info))
100107

101108
if s == mem_s:
102109
pass
103110

104111
if insert_flag == 0:
105112
insert_flag = 1
106-
tmp_map_info.append([mem_s, mem_e, mem_p, mem_info])
113+
tmp_map_info.append((mem_s, mem_e, mem_p, mem_info))
107114

108115
if e > mem_e:
109-
tmp_map_info.append([mem_e, e, p, info])
116+
tmp_map_info.append((mem_e, e, p, info))
110117

111118
if e == mem_e:
112119
pass
120+
113121
if insert_flag == 0:
114-
tmp_map_info.append([mem_s, mem_e, mem_p, mem_info])
122+
tmp_map_info.append((mem_s, mem_e, mem_p, mem_info))
115123

116124
self.map_info = tmp_map_info
117125

118-
119126
def del_mapinfo(self, mem_s: int, mem_e: int):
120127
"""Subtract a memory range from map.
121128
@@ -124,7 +131,7 @@ def del_mapinfo(self, mem_s: int, mem_e: int):
124131
mem_e: memory range end
125132
"""
126133

127-
tmp_map_info = []
134+
tmp_map_info: MutableSequence[MapInfoEntry] = []
128135

129136
for s, e, p, info in self.map_info:
130137
if e <= mem_s:
@@ -187,11 +194,9 @@ def show_mapinfo(self):
187194
for lbound, ubound, perms, label, container in self.get_mapinfo():
188195
self.ql.log.info(f'{lbound:08x} - {ubound:08x} {perms:5s} {label:12s} {container or ""}')
189196

197+
# TODO: relying on the label string is risky; find a more reliable method
190198
def get_lib_base(self, filename: str) -> int:
191-
for s, e, p, info in self.map_info:
192-
if os.path.split(info)[1] == filename:
193-
return s
194-
return -1
199+
return next((s for s, _, _, info in self.map_info if os.path.split(info)[1] == filename), -1)
195200

196201
def align(self, addr: int, alignment: int = 0x1000) -> int:
197202
"""Round up to nearest alignment.
@@ -202,17 +207,20 @@ def align(self, addr: int, alignment: int = 0x1000) -> int:
202207
"""
203208

204209
# rounds up to nearest alignment
205-
mask = ((1 << self.ql.archbit) - 1) & -alignment
210+
mask = self.max_mem_addr & -alignment
211+
206212
return (addr + (alignment - 1)) & mask
207213

208214
# save all mapped mem
209215
def save(self):
210216
mem_dict = {}
211217
seq = 1
218+
212219
for start, end, perm, info in self.map_info:
213-
mem_read = self.read(start, end-start)
220+
mem_read = self.read(start, end-start)
214221
mem_dict[seq] = start, end, perm, info, mem_read
215222
seq += 1
223+
216224
return mem_dict
217225

218226
# restore all dumped memory
@@ -257,16 +265,17 @@ def read_ptr(self, addr: int, size: int=None) -> int:
257265
if not size:
258266
size = self.ql.pointersize
259267

260-
if size == 1:
261-
return self.ql.unpack8(self.read(addr, 1))
262-
elif size == 2:
263-
return self.ql.unpack16(self.read(addr, 2))
264-
elif size == 4:
265-
return self.ql.unpack32(self.read(addr, 4))
266-
elif size == 8:
267-
return self.ql.unpack64(self.read(addr, 8))
268-
else:
269-
raise QlErrorStructConversion(f"Unsupported pointer size: {size}")
268+
__unpack = {
269+
1 : self.ql.unpack8,
270+
2 : self.ql.unpack16,
271+
4 : self.ql.unpack32,
272+
8 : self.ql.unpack64
273+
}.get(size)
274+
275+
if __unpack:
276+
return __unpack(self.read(addr, size))
277+
278+
raise QlErrorStructConversion(f"Unsupported pointer size: {size}")
270279

271280
def write(self, addr: int, data: bytes) -> None:
272281
"""Write bytes to a memory.
@@ -280,8 +289,8 @@ def write(self, addr: int, data: bytes) -> None:
280289
self.ql.uc.mem_write(addr, data)
281290
except:
282291
self.show_mapinfo()
283-
self.ql.log.debug("addresss write length: " + str(len(data)))
284-
self.ql.log.error("addresss write error: " + hex(addr))
292+
self.ql.log.debug(f'addresss write length: {len(data):d}')
293+
self.ql.log.error(f'addresss write error: {addr:#x}')
285294
raise
286295

287296
def search(self, needle: bytes, begin: int = None, end: int = None):
@@ -320,15 +329,13 @@ def unmap(self, addr: int, size: int) -> None:
320329
self.del_mapinfo(addr, addr + size)
321330
self.ql.uc.mem_unmap(addr, size)
322331

323-
324332
def unmap_all(self):
325333
"""Reclaim the entire memory space.
326334
"""
327335

328-
for region in list(self.ql.uc.mem_regions()):
329-
if region[0] and region[1]:
330-
return self.unmap(region[0], ((region[1] - region[0])+0x1))
331-
336+
for begin, end, _ in self.ql.uc.mem_regions():
337+
if begin and end:
338+
self.unmap(begin, end - begin + 1)
332339

333340
def is_available(self, addr, size):
334341
'''
@@ -525,26 +532,28 @@ def __init__(self, ql: Qiling, start_address: int, end_address: int):
525532
self.current_use = 0
526533
# save all memory regions allocated
527534
self.mem_alloc = []
528-
529-
def save(self):
530-
saved_state = {}
531-
saved_state['chunks'] = self.chunks
532-
saved_state['start_address'] = self.start_address
533-
saved_state['end_address'] = self.end_address
534-
saved_state['page_size'] = self.page_size
535-
saved_state['current_alloc'] = self.current_alloc
536-
saved_state['current_use'] = self.current_use
537-
saved_state['mem_alloc'] = self.mem_alloc
535+
536+
def save(self) -> Mapping[str, Any]:
537+
saved_state = {
538+
'chunks' : self.chunks,
539+
'start_address' : self.start_address,
540+
'end_address' : self.end_address,
541+
'page_size' : self.page_size,
542+
'current_alloc' : self.current_alloc,
543+
'current_use' : self.current_use,
544+
'mem_alloc' : self.mem_alloc
545+
}
546+
538547
return saved_state
539548

540-
def restore(self, saved_state):
541-
self.chunks = saved_state['chunks']
542-
self.start_address = saved_state['start_address']
543-
self.end_address = saved_state['end_address']
544-
self.page_size = saved_state['page_size']
545-
self.current_alloc = saved_state['current_alloc']
546-
self.current_use = saved_state['current_use']
547-
self.mem_alloc = saved_state['mem_alloc']
549+
def restore(self, saved_state: Mapping[str, Any]):
550+
self.chunks = saved_state['chunks']
551+
self.start_address = saved_state['start_address']
552+
self.end_address = saved_state['end_address']
553+
self.page_size = saved_state['page_size']
554+
self.current_alloc = saved_state['current_alloc']
555+
self.current_use = saved_state['current_use']
556+
self.mem_alloc = saved_state['mem_alloc']
548557

549558
def alloc(self, size: int):
550559
# Find the heap chunks that best matches size

0 commit comments

Comments
 (0)