Skip to content

Commit dc9aa8a

Browse files
committed
Rearrange enum convertion methods
1 parent fc2c8c8 commit dc9aa8a

File tree

6 files changed

+33
-56
lines changed

6 files changed

+33
-56
lines changed

qiling/const.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55

66
from enum import Enum, Flag, IntEnum
7-
from typing import Any, Mapping, Type
7+
from typing import Mapping, Type, TypeVar
88

99
class QL_ENDIAN(IntEnum):
1010
EL = 1
@@ -66,16 +66,17 @@ class QL_STOP(Flag):
6666
QL_HOOK_BLOCK = 0b0001
6767
QL_CALL_BLOCK = 0b0010
6868

69-
def __reverse_enum(e: Type[Enum]) -> Mapping[str, Any]:
70-
'''Create a reverse mapping for an enum.
69+
T = TypeVar('T', bound=Enum)
70+
def __casefold_enum(e: Type[T]) -> Mapping[str, T]:
71+
'''Create a casefolded mapping of an enum to allow case-insensitive lookup.
7172
'''
7273

73-
return dict((v.name.lower(), v) for v in e.__members__.values())
74+
return dict((k.casefold(), v) for k, v in e._member_map_.items())
7475

75-
debugger_map: Mapping[str, QL_DEBUGGER] = __reverse_enum(QL_DEBUGGER)
76-
arch_map : Mapping[str, QL_ARCH] = __reverse_enum(QL_ARCH)
77-
os_map : Mapping[str, QL_OS] = __reverse_enum(QL_OS)
78-
verbose_map : Mapping[str, QL_VERBOSE] = __reverse_enum(QL_VERBOSE)
76+
debugger_map = __casefold_enum(QL_DEBUGGER)
77+
arch_map = __casefold_enum(QL_ARCH)
78+
os_map = __casefold_enum(QL_OS)
79+
verbose_map = __casefold_enum(QL_VERBOSE)
7980

8081
arch_os_map = {
8182
QL_ARCH.EVM : QL_OS.EVM,

qiling/core.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def __init__(
122122
archtype = arch_convert(archtype)
123123

124124
if type(ostype) is str:
125-
ostype = ostype_convert(ostype)
125+
ostype = os_convert(ostype)
126126

127127
# if provided arch was invalid or not provided, guess arch and os
128128
if archtype is None:
@@ -141,23 +141,18 @@ def __init__(
141141
ostype = arch_os_convert(archtype)
142142

143143
# arch should have been determined by now; fail if not
144-
if archtype is None or not ql_is_valid_arch(archtype):
144+
if type(archtype) is not QL_ARCH:
145145
raise QlErrorArch(f'Uknown or unsupported architecture: "{archtype}"')
146146

147147
# os should have been determined by now; fail if not
148-
if ostype is None or not ql_is_valid_ostype(ostype):
148+
if type(ostype) is not QL_OS:
149149
raise QlErrorOsType(f'Unknown or unsupported operating system: "{ostype}"')
150150

151151
# if endianess is still undetermined, set it to little-endian.
152152
# this setting is ignored for architectures with predfined endianess
153153
if endian is None:
154154
endian = QL_ENDIAN.EL
155155

156-
# make sure args were canonicalized successfully
157-
assert type(archtype) is QL_ARCH
158-
assert type(ostype) is QL_OS
159-
assert type(endian) is QL_ENDIAN
160-
161156
self._arch = arch_setup(archtype, endian, thumb, self)
162157

163158
self.uc = self.arch.uc

qiling/debugger/gdb/gdb.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ def handle_q(subcmd):
483483
elif subcmd.startswith('Xfer:features:read'):
484484
xfercmd_file = subcmd.split(':')[3]
485485
xfercmd_abspath = os.path.dirname(os.path.abspath(__file__))
486-
xml_folder = arch_convert_str(self.ql.arch.type).lower()
486+
xml_folder = self.ql.arch.type.name.lower()
487487
xfercmd_file = os.path.join(xfercmd_abspath,"xml",xml_folder, xfercmd_file)
488488

489489
if os.path.exists(xfercmd_file) and self.ql.os.type is not QL_OS.WINDOWS:

qiling/host.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def os(self) -> Optional[QL_OS]:
2121

2222
system = platform.system()
2323

24-
return utils.ostype_convert(system.lower())
24+
return utils.os_convert(system)
2525

2626
@cached_property
2727
def arch(self) -> Optional[QL_ARCH]:
@@ -30,4 +30,4 @@ def arch(self) -> Optional[QL_ARCH]:
3030

3131
machine = platform.machine()
3232

33-
return utils.arch_convert(machine.lower())
33+
return utils.arch_convert(machine)

qiling/os/posix/posix.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from qiling.exception import QlErrorSyscallNotFound
1919
from qiling.os.os import QlOs
2020
from qiling.os.posix.const import errors
21-
from qiling.utils import ostype_convert_str, ql_get_module_function, ql_syscall_mapping_function
21+
from qiling.utils import ql_get_module_function, ql_syscall_mapping_function
2222

2323
from qiling.os.posix.syscall import *
2424
from qiling.os.linux.syscall import *
@@ -231,7 +231,7 @@ def load_syscall(self):
231231
def __get_os_module(osname: str):
232232
return ql_get_module_function(f'qiling.os.{osname.lower()}', 'syscall')
233233

234-
os_syscalls = __get_os_module(ostype_convert_str(self.type))
234+
os_syscalls = __get_os_module(self.type.name)
235235
posix_syscalls = __get_os_module('posix')
236236

237237
# look in os-specific and posix syscall hooks

qiling/utils.py

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
import importlib, os, pefile, yaml
1313

1414
from configparser import ConfigParser
15-
from typing import Any, Container, Optional, Tuple, Type, Union
16-
from enum import Enum
15+
from typing import Any, Mapping, Optional, Tuple, Type, Union
1716

1817
from unicorn import UC_ERR_READ_UNMAPPED, UC_ERR_FETCH_UNMAPPED
1918

@@ -31,49 +30,31 @@ def wrapper(*args, **kw):
3130

3231
return wrapper
3332

34-
def enum_values(e: Type[Enum]) -> Container:
35-
return e.__members__.values()
33+
def __name_to_enum(name: str, mapping: Mapping[str, T], aliases: Mapping[str, str] = {}) -> Optional[T]:
34+
key = name.casefold()
3635

37-
def ql_is_valid_ostype(ostype: QL_OS) -> bool:
38-
return ostype in enum_values(QL_OS)
36+
return mapping.get(aliases.get(key) or key)
3937

40-
def ql_is_valid_arch(arch: QL_ARCH) -> bool:
41-
return arch in enum_values(QL_ARCH)
42-
43-
def __value_to_key(e: Type[Enum], val: Any) -> Optional[str]:
44-
key = e._value2member_map_[val]
45-
46-
return None if key is None else key.name
47-
48-
def ostype_convert_str(ostype: QL_OS) -> Optional[str]:
49-
return __value_to_key(QL_OS, ostype)
50-
51-
def ostype_convert(ostype: str) -> Optional[QL_OS]:
38+
def os_convert(os: str) -> Optional[QL_OS]:
5239
alias_map = {
53-
"darwin": "macos",
40+
'darwin' : 'macos'
5441
}
5542

56-
return os_map.get(alias_map.get(ostype, ostype))
57-
58-
def arch_convert_str(arch: QL_ARCH) -> Optional[str]:
59-
return __value_to_key(QL_ARCH, arch)
43+
return __name_to_enum(os, os_map, alias_map)
6044

6145
def arch_convert(arch: str) -> Optional[QL_ARCH]:
6246
alias_map = {
63-
"x86_64": "x8664",
64-
"riscv32": "riscv",
47+
'x86_64' : 'x8664',
48+
'riscv32' : 'riscv'
6549
}
66-
67-
return arch_map.get(alias_map.get(arch, arch))
6850

69-
def arch_os_convert(arch: QL_ARCH) -> Optional[QL_OS]:
70-
return arch_os_map.get(arch)
51+
return __name_to_enum(arch, arch_map, alias_map)
7152

7253
def debugger_convert(debugger: str) -> Optional[QL_DEBUGGER]:
73-
return debugger_map.get(debugger)
54+
return __name_to_enum(debugger, debugger_map)
7455

75-
def debugger_convert_str(debugger_id: QL_DEBUGGER) -> Optional[str]:
76-
return __value_to_key(QL_DEBUGGER, debugger_id)
56+
def arch_os_convert(arch: QL_ARCH) -> Optional[QL_OS]:
57+
return arch_os_map.get(arch)
7758

7859
# Call `function_name` in `module_name`.
7960
# e.g. map_syscall in qiling.os.linux.map_syscall
@@ -368,7 +349,7 @@ def arch_setup(archtype: QL_ARCH, endian: QL_ENDIAN, thumb: bool, ql):
368349
}[archtype]
369350

370351
qlarch_path = f'qiling.arch.{module}'
371-
qlarch_class = f'QlArch{arch_convert_str(archtype).upper()}'
352+
qlarch_class = f'QlArch{archtype.name.upper()}'
372353

373354
obj = ql_get_module_function(qlarch_path, qlarch_class)
374355

@@ -377,7 +358,7 @@ def arch_setup(archtype: QL_ARCH, endian: QL_ENDIAN, thumb: bool, ql):
377358

378359
# This function is extracted from os_setup (QlOsPosix) so I put it here.
379360
def ql_syscall_mapping_function(ostype: QL_OS, archtype: QL_ARCH):
380-
qlos_name = ostype_convert_str(ostype)
361+
qlos_name = ostype.name
381362
qlos_path = f'qiling.os.{qlos_name.lower()}.map_syscall'
382363
qlos_func = 'get_syscall_mapper'
383364

@@ -409,7 +390,7 @@ def profile_setup(ql, ostype: QL_OS, filename: Optional[str]):
409390

410391
else:
411392
qiling_home = os.path.dirname(os.path.abspath(__file__))
412-
os_profile = os.path.join(qiling_home, 'profiles', f'{ostype_convert_str(ostype).lower()}.ql')
393+
os_profile = os.path.join(qiling_home, 'profiles', f'{ostype.name.lower()}.ql')
413394

414395
profiles = [os_profile]
415396

0 commit comments

Comments
 (0)