Skip to content

Commit 48446b6

Browse files
committed
Refactor register
1 parent 69b825c commit 48446b6

File tree

1 file changed

+78
-55
lines changed

1 file changed

+78
-55
lines changed

qiling/arch/register.py

Lines changed: 78 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,126 +3,149 @@
33
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
44
#
55

6-
class QlRegisterManager():
7-
"""
8-
This class exposes the ql.reg features that allows you to directly access
6+
from typing import Any, Mapping, MutableMapping, Union
7+
8+
from qiling import Qiling
9+
10+
class QlRegisterManager:
11+
"""This class exposes the ql.reg features that allows you to directly access
912
or assign values to CPU registers of a particular architecture.
1013
1114
Registers exposed are listed in the *_const.py files in the respective
1215
arch directories and are mapped to Unicorn Engine's definitions
1316
"""
14-
def __init__(self, ql):
15-
self.register_mapping = {}
16-
self.reverse_mapping = {}
17+
18+
__priv_members = ('register_mapping', 'ql', 'uc_pc', 'uc_sp')
19+
20+
def __init__(self, ql: Qiling):
21+
self.register_mapping: MutableMapping[str, int] = {}
22+
self.reverse_mapping: Mapping[int, str] = {}
1723
self.ql = ql
1824
self.uc_pc = 0
1925
self.uc_sp = 0
20-
2126

22-
def __getattribute__(self, name):
27+
def __getattribute__(self, name: str) -> Any:
2328
name = name.lower()
24-
if name in ("register_mapping", "ql", "uc_pc", "uc_sp"):
25-
return super(QlRegisterManager, self).__getattribute__(name)
29+
30+
if name in QlRegisterManager.__priv_members:
31+
return super().__getattribute__(name)
2632

2733
elif name in self.register_mapping:
2834
return self.ql.uc.reg_read(self.register_mapping[name])
2935

30-
return super(QlRegisterManager, self).__getattribute__(name)
36+
return super().__getattribute__(name)
37+
3138

39+
def __setattr__(self, name: str, value: Any):
40+
name = name.lower()
3241

33-
def __setattr__(self, name, value):
34-
name=name.lower()
35-
if name in ("register_mapping", "ql", "uc_pc", "uc_sp"):
36-
super(QlRegisterManager, self).__setattr__(name, value)
42+
if name in QlRegisterManager.__priv_members:
43+
super().__setattr__(name, value)
3744

3845
elif name in self.register_mapping:
3946
self.ql.uc.reg_write(self.register_mapping[name], value)
40-
else:
41-
super(QlRegisterManager, self).__setattr__(name, value)
4247

48+
super().__setattr__(name, value)
49+
50+
51+
def expand_mapping(self, extra: Mapping[str, int]) -> None:
52+
"""Expand registers mapping with additional ones.
53+
"""
4354

44-
def expand_mapping(self, expanded_map):
45-
self.register_mapping = {**self.register_mapping, **expanded_map}
55+
self.register_mapping.update(extra)
4656

4757

4858
# read register
49-
def read(self, register):
50-
if isinstance(register, str):
51-
register = self.register_mapping.get(register.lower(), None)
59+
def read(self, register: Union[str, int]):
60+
"""Read a register value.
61+
"""
62+
63+
if type(register) is str:
64+
register = self.register_mapping[register.lower()]
65+
5266
return self.ql.uc.reg_read(register)
5367

5468

55-
def write(self, register, value):
56-
if isinstance(register, str):
57-
register = self.register_mapping.get(register.lower(), None)
69+
def write(self, register: Union[str, int], value: int) -> None:
70+
"""Write a register value.
71+
"""
72+
73+
if type(register) is str:
74+
register = self.register_mapping[register.lower()]
75+
5876
return self.ql.uc.reg_write(register, value)
5977

6078

61-
def msr(self, msr, addr= None):
62-
if not addr:
79+
def msr(self, msr: int, value: int = None):
80+
"""Read or write a model-specific register (MSR) value.
81+
Intel architecture only
82+
"""
83+
84+
if value is None:
6385
return self.ql.uc.msr_read(msr)
64-
else:
65-
self.ql.uc.msr_write(msr, addr)
86+
87+
self.ql.uc.msr_write(msr, value)
88+
89+
90+
def save(self) -> MutableMapping[str, Any]:
91+
"""Save CPU context.
92+
"""
93+
94+
return dict((reg, self.read(reg)) for reg in self.register_mapping)
6695

6796

68-
# ql.reg.save
69-
def save(self):
70-
reg_dict = {}
71-
for reg in self.register_mapping:
72-
reg_v = self.read(reg)
73-
reg_dict[reg] = reg_v
74-
return reg_dict
97+
def restore(self, context: MutableMapping[str, Any] = {}) -> None:
98+
"""Restore CPU context.
99+
"""
75100

101+
for reg, val in context.items():
102+
self.write(reg, val)
76103

77-
# ql.reg.restore
78-
def restore(self, value = {}):
79-
for reg in self.register_mapping:
80-
reg_v= value[reg]
81-
self.write(reg, reg_v)
82104

105+
# TODO: This needs to be implemented for all archs
106+
def bit(self, reg: Union[str, int]) -> int:
107+
"""Get register size in bits.
108+
"""
83109

84-
# ql.reg.bit() - Register bit
85-
#FIXME: This needs to be implemented for all archs
86-
def bit(self, uc_reg):
87-
return self.ql.arch.get_reg_bit(uc_reg)
110+
return self.ql.arch.get_reg_bit(reg)
88111

89112

90113
# Generic methods to get SP and IP across Arch's #
91114
# These functions should only be used if the #
92115
# caller is dealing with multiple Arch's #
93-
def register_sp(self, sp_id):
116+
def register_sp(self, sp_id: int):
94117
self.uc_sp = sp_id
95118

96119

97-
def register_pc(self, pc_id):
120+
def register_pc(self, pc_id: int):
98121
self.uc_pc = pc_id
99122

100123

101124
@property
102-
def arch_pc(self):
125+
def arch_pc(self) -> int:
103126
return self.ql.uc.reg_read(self.uc_pc)
104127

105128

106129
@arch_pc.setter
107-
def arch_pc(self, value):
130+
def arch_pc(self, value: int) -> None:
108131
return self.ql.uc.reg_write(self.uc_pc, value)
109132

110133
@property
111-
def arch_pc_name(self):
112-
return self.ql.reg.reverse_mapping[self.uc_pc]
134+
def arch_pc_name(self) -> str:
135+
return self.reverse_mapping[self.uc_pc]
113136

114137
@property
115-
def arch_sp(self):
138+
def arch_sp(self) -> int:
116139
return self.ql.uc.reg_read(self.uc_sp)
117140

118141

119142
@arch_sp.setter
120-
def arch_sp(self, value):
143+
def arch_sp(self, value: int) -> None:
121144
return self.ql.uc.reg_write(self.uc_sp, value)
122145

123146

124-
def get_uc_reg(self, uc_reg_name):
125-
return self.register_mapping.get(uc_reg_name, None)
147+
def get_uc_reg(self, reg_name: str) -> int:
148+
return self.register_mapping[reg_name]
126149

127150

128151
def create_reverse_mapping(self):

0 commit comments

Comments
 (0)