Skip to content

Commit 706f0f0

Browse files
committed
add memory.py
1 parent 7de9161 commit 706f0f0

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

qiling/debugger/qdb/memory.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
4+
#
5+
6+
from qiling.utils import ql_get_module_function
7+
from qiling.const import QL_ARCH
8+
9+
from .context import Context
10+
from .arch import ArchCORTEX_M, ArchARM, ArchMIPS, ArchX86
11+
12+
class MemoryManager(Context, ArchX86, ArchCORTEX_M, ArchARM, ArchMIPS):
13+
"""
14+
memory manager for handing memory access
15+
"""
16+
17+
def __init__(self, ql):
18+
super().__init__(ql)
19+
20+
for arch in ("ArchARM", "ArchMIPS", "ArchCORTEX_M", "ArchX86"):
21+
if ql.archtype.name in str(arch):
22+
imp_arch = ql_get_module_function("qiling.debugger.qdb.arch", arch)
23+
24+
imp_arch.__init__(self)
25+
26+
self.DEFAULT_FMT = ('x', 4, 1)
27+
28+
self.FORMAT_LETTER = {
29+
"o", # octal
30+
"x", # hex
31+
"d", # decimal
32+
"u", # unsigned decimal
33+
"t", # binary
34+
"f", # float
35+
"a", # address
36+
"i", # instruction
37+
"c", # char
38+
"s", # string
39+
"z", # hex, zero padded on the left
40+
}
41+
42+
self.SIZE_LETTER = {
43+
"b": 1, # 1-byte, byte
44+
"h": 2, # 2-byte, halfword
45+
"w": 4, # 4-byte, word
46+
"g": 8, # 8-byte, giant
47+
}
48+
49+
def extract_count(self, t):
50+
return "".join([s for s in t if s.isdigit()])
51+
52+
def get_fmt(self, text):
53+
f, s, c = self.DEFAULT_FMT
54+
if self.extract_count(text):
55+
c = int(self.extract_count(text))
56+
57+
for char in text.strip(str(c)):
58+
if char in self.SIZE_LETTER.keys():
59+
s = self.SIZE_LETTER.get(char)
60+
61+
elif char in self.FORMAT_LETTER:
62+
f = char
63+
64+
return (f, s, c)
65+
66+
def fmt_unpack(self, bs: bytes, sz: int) -> int:
67+
return {
68+
1: lambda x: x[0],
69+
2: self.ql.unpack16,
70+
4: self.ql.unpack32,
71+
8: self.ql.unpack64,
72+
}.get(sz)(bs)
73+
74+
def parse(self, line: str):
75+
args = line.split()
76+
77+
if line.startswith("/"): # followed by format letter and size letter
78+
79+
fmt, *rest = line.strip("/").split()
80+
81+
rest = "".join(rest)
82+
83+
fmt = self.get_fmt(fmt)
84+
85+
elif len(args) == 1: # only address
86+
rest = args[0]
87+
fmt = self.DEFAULT_FMT
88+
89+
else:
90+
rest = args
91+
92+
if self.ql.archtype in (QL_ARCH.ARM, QL_ARCH.ARM_THUMB):
93+
rest = rest.replace("fp", "r11")
94+
95+
elif self.ql.archtype == QL_ARCH.MIPS:
96+
rest = rest.replace("fp", "s8")
97+
98+
# for supporting addition of register with constant value
99+
elems = rest.split("+")
100+
elems = [elem.strip("$") for elem in elems]
101+
102+
items = []
103+
104+
for elem in elems:
105+
if elem in self.ql.reg.register_mapping.keys():
106+
if (value := self.ql.reg.read(elem)):
107+
items.append(value)
108+
else:
109+
items.append(self.read_int(elem))
110+
111+
addr = sum(items)
112+
113+
ft, sz, ct = fmt
114+
115+
if ft == "i":
116+
117+
for offset in range(addr, addr+ct*4, 4):
118+
line = self.disasm(offset)
119+
if line:
120+
print(f"0x{line.address:x}: {line.mnemonic}\t{line.op_str}")
121+
122+
print()
123+
124+
else:
125+
lines = 1 if ct <= 4 else math.ceil(ct / 4)
126+
127+
mem_read = []
128+
for offset in range(ct):
129+
# append data if read successfully, otherwise return error message
130+
if (data := self.try_read(addr+(offset*sz), sz))[0] is not None:
131+
mem_read.append(data[0])
132+
133+
else:
134+
return data[1]
135+
136+
for line in range(lines):
137+
offset = line * sz * 4
138+
print(f"0x{addr+offset:x}:\t", end="")
139+
140+
idx = line * self.ql.pointersize
141+
for each in mem_read[idx:idx+self.ql.pointersize]:
142+
data = self.fmt_unpack(each, sz)
143+
prefix = "0x" if ft in ("x", "a") else ""
144+
pad = '0' + str(sz*2) if ft in ('x', 'a', 't') else ''
145+
ft = ft.lower() if ft in ("x", "o", "b", "d") else ft.lower().replace("t", "b").replace("a", "x")
146+
print(f"{prefix}{data:{pad}{ft}}\t", end="")
147+
148+
print()
149+
150+
return True

0 commit comments

Comments
 (0)