Skip to content

Commit f0f558f

Browse files
authored
Merge pull request #962 from elicn/misc-improv
Clean and tidy-up various modules
2 parents f050f42 + de43219 commit f0f558f

File tree

5 files changed

+176
-213
lines changed

5 files changed

+176
-213
lines changed

qiling/const.py

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

6-
from enum import EnumMeta, IntEnum
7-
from typing import Mapping, TypeVar
6+
from enum import Enum, IntEnum
7+
from typing import Any, Mapping, Type
88

99
class QL_ENDIAN(IntEnum):
1010
EL = 1
@@ -69,9 +69,7 @@ class QL_INTERCEPT(IntEnum):
6969
QL_HOOK_BLOCK = 0b0001
7070
QL_CALL_BLOCK = 0b0010
7171

72-
__QL_CE = TypeVar('__QL_CE', QL_DEBUGGER, QL_ARCH, QL_OS, QL_VERBOSE)
73-
74-
def __reverse_enum(e: EnumMeta) -> Mapping[str, __QL_CE]:
72+
def __reverse_enum(e: Type[Enum]) -> Mapping[str, Any]:
7573
'''Create a reverse mapping for an enum.
7674
'''
7775

qiling/debugger/gdb/gdb.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ def handle_q(subcmd):
493493
elif subcmd.startswith('Xfer:features:read'):
494494
xfercmd_file = subcmd.split(':')[3]
495495
xfercmd_abspath = os.path.dirname(os.path.abspath(__file__))
496-
xml_folder = arch_convert_str(self.ql.archtype)
496+
xml_folder = arch_convert_str(self.ql.archtype).lower()
497497
xfercmd_file = os.path.join(xfercmd_abspath,"xml",xml_folder, xfercmd_file)
498498

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

qiling/extensions/trace.py

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

99
from capstone import Cs, CsInsn, CS_OP_IMM, CS_OP_MEM, CS_OP_REG
1010
from capstone.x86 import X86Op
11-
from capstone.x86_const import X86_INS_LEA
12-
13-
from unicorn.x86_const import UC_X86_REG_INVALID, UC_X86_REG_RIP
11+
from capstone.x86_const import X86_INS_LEA, X86_REG_INVALID, X86_REG_RIP
1412

1513
from qiling import Qiling
1614

@@ -54,14 +52,14 @@ def __to_trace_line(record: TraceRecord, symsmap: Mapping[int, str] = {}) -> str
5452
# current instruction instead of the next one.
5553
#
5654
# here we patch rip value recorded in state to point to the next instruction boundary
57-
state = tuple((reg, val + insn.size if reg == UC_X86_REG_RIP else val) for reg, val in state)
55+
state = tuple((reg, val + insn.size if reg == X86_REG_RIP else val) for reg, val in state)
5856

5957
def __read_reg(reg: int) -> int:
6058
"""[internal] Read a register value from the recorded state. Only registers that were
6159
referenced by the current instruction can be read.
6260
"""
6361

64-
return 0 if reg == UC_X86_REG_INVALID else next(v for r, v in state if r == reg)
62+
return 0 if reg == X86_REG_INVALID else next(v for r, v in state if r == reg)
6563

6664
def __resolve(address: int) -> str:
6765
"""[internal] Find the symbol that matches to the specified address (if any).
@@ -114,11 +112,10 @@ def __parse_op(op: X86Op) -> str:
114112
# unexpected op type
115113
raise RuntimeError
116114

117-
opcode = ''.join(f'{b:02x}' for b in insn.bytes)
118115
operands = ', '.join(__parse_op(o) for o in insn.operands)
119116
reads = ', '.join(f'{insn.reg_name(reg)} = {val:#x}' for reg, val in state)
120117

121-
return f'{insn.address:08x} | {opcode:24s} {insn.mnemonic:10} {operands:56s} | {reads}'
118+
return f'{insn.address:08x} | {insn.bytes.hex():24s} {insn.mnemonic:10} {operands:56s} | {reads}'
122119

123120
def enable_full_trace(ql: Qiling):
124121
"""Enable instruction-level tracing.

qiling/os/path.py

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

6-
from typing import Any, Mapping
7-
import ctypes, os, uuid
8-
9-
from pathlib import Path, PurePosixPath, PureWindowsPath, PosixPath, WindowsPath
10-
from unicorn import UcError
6+
import os
7+
from typing import Union
8+
from pathlib import Path, PurePath, PurePosixPath, PureWindowsPath
119

1210
from qiling import Qiling
13-
from qiling.os.windows.wdk_const import *
14-
from qiling.os.windows.structs import *
15-
from qiling.utils import verify_ret
11+
from qiling.const import QL_OS, QL_OS_POSIX
1612

1713
# OH-MY-WIN32 !!!
1814
# Some codes from cygwin.
@@ -25,27 +21,24 @@ class QlPathManager:
2521
def __init__(self, ql: Qiling, cwd: str):
2622
self.ql = ql
2723
self._cwd = cwd
28-
24+
2925
@property
30-
def cwd(self):
26+
def cwd(self) -> str:
3127
return self._cwd
32-
28+
3329
@cwd.setter
34-
def cwd(self, c):
35-
if c[0] != "/":
36-
self.ql.log.warning(f"Sanity check: cur_path doesn't start with a /!")
30+
def cwd(self, c: str) -> None:
31+
if not c.startswith('/'):
32+
self.ql.log.warning(f'Sanity check: path does not start with a forward slash "/"')
33+
3734
self._cwd = c
3835

3936
@staticmethod
40-
def normalize(path):
41-
if type(path) is PurePosixPath:
42-
normalized_path = PurePosixPath()
43-
elif type(path) is PureWindowsPath:
44-
normalized_path = PureWindowsPath()
45-
elif type(path) is PosixPath:
46-
normalized_path = PosixPath()
47-
elif type(path) is WindowsPath:
48-
normalized_path = WindowsPath()
37+
def normalize(path: Union[Path, PurePath]) -> Union[Path, PurePath]:
38+
# expected types: PosixPath, PurePosixPath, WindowsPath, PureWindowsPath
39+
assert isinstance(path, (Path, PurePath)), f'did not expect {type(path).__name__!r} here'
40+
41+
normalized_path = type(path)()
4942

5043
# remove anchor (necessary for Windows UNC paths) and convert to relative path
5144
if path.is_absolute():
@@ -64,101 +57,103 @@ def normalize(path):
6457
return normalized_path
6558

6659
@staticmethod
67-
def convert_win32_to_posix(rootfs, cwd, path):
68-
# rootfs is a concrete path.
69-
rootfs = Path(rootfs)
70-
# cwd and path are pure paths
71-
cwd = PurePosixPath(cwd[1:])
60+
def convert_win32_to_posix(rootfs: Union[str, Path], cwd: str, path: str) -> Path:
61+
_rootfs = Path(rootfs)
62+
_cwd = PurePosixPath(cwd[1:])
7263

73-
result = None
7464
# Things are complicated here.
7565
# See https://docs.microsoft.com/zh-cn/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN
7666
if PureWindowsPath(path).is_absolute():
77-
if (len(path) >= 2 and path[0] == '\\' and path[1] == '\\') or \
78-
(len(path) >= 3 and path[0].isalpha() and path[2] == '\\'): # \\.\PhysicalDrive0 or \\Server\Share\Directory or X:\
67+
if (len(path) >= 2 and path.startswith(r'\\')) or \
68+
(len(path) >= 3 and path[0].isalpha() and path[1:3] == ':\\'): # \\.\PhysicalDrive0 or \\Server\Share\Directory or X:\
7969
# UNC path should be handled in fs mapping. If not, append it to rootfs directly.
8070
pw = PureWindowsPath(path)
81-
result = rootfs / QlPathManager.normalize(pw)
71+
result = _rootfs / QlPathManager.normalize(pw)
8272
else:
8373
# code should never reach here.
84-
result = rootfs / QlPathManager.normalize(path)
74+
result = _rootfs / QlPathManager.normalize(path)
8575
else:
8676
if len(path) >= 3 and path[:3] == r'\\?' or path[:3] == r'\??': # \??\ or \\?\ or \Device\..
8777
# Similair to \\.\, it should be handled in fs mapping.
8878
pw = PureWindowsPath(path)
89-
result = rootfs / QlPathManager.normalize(cwd / pw.relative_to(pw.anchor).as_posix())
79+
result = _rootfs / QlPathManager.normalize(_cwd / pw.relative_to(pw.anchor).as_posix())
9080
else:
9181
# a normal relative path
92-
result = rootfs / QlPathManager.normalize(cwd / PureWindowsPath(path).as_posix())
82+
result = _rootfs / QlPathManager.normalize(_cwd / PureWindowsPath(path).as_posix())
83+
9384
return result
9485

9586
@staticmethod
96-
def convert_posix_to_win32(rootfs, cwd, path):
97-
# rootfs is a concrete path.
98-
rootfs = Path(rootfs)
99-
# cwd and path are pure paths
100-
cwd = PurePosixPath(cwd[1:])
101-
path = PurePosixPath(path)
102-
if path.is_absolute():
103-
return rootfs / QlPathManager.normalize(path)
87+
def convert_posix_to_win32(rootfs: Union[str, Path], cwd: str, path: str) -> Path:
88+
_rootfs = Path(rootfs)
89+
_cwd = PurePosixPath(cwd[1:])
90+
_path = PurePosixPath(path)
91+
92+
if _path.is_absolute():
93+
return _rootfs / QlPathManager.normalize(_path)
10494
else:
105-
return rootfs / QlPathManager.normalize(cwd / path)
95+
return _rootfs / QlPathManager.normalize(_cwd / _path)
10696

10797
@staticmethod
108-
def convert_for_native_os(rootfs, cwd, path):
109-
rootfs = Path(rootfs)
110-
cwd = PurePosixPath(cwd[1:])
111-
path = Path(path)
112-
if path.is_absolute():
113-
return rootfs / QlPathManager.normalize(path)
98+
def convert_for_native_os(rootfs: Union[str, Path], cwd: str, path: str) -> Path:
99+
_rootfs = Path(rootfs)
100+
_cwd = PurePosixPath(cwd[1:])
101+
_path = Path(path)
102+
103+
if _path.is_absolute():
104+
return _rootfs / QlPathManager.normalize(_path)
114105
else:
115-
return rootfs / QlPathManager.normalize(cwd / path.as_posix())
106+
return _rootfs / QlPathManager.normalize(_cwd / _path.as_posix())
116107

117-
def convert_path(self, rootfs, cwd, path):
118-
if (self.ql.ostype == self.ql.platform ) \
119-
or (self.ql.ostype in [QL_OS.LINUX, QL_OS.MACOS] and self.ql.platform in [QL_OS.LINUX, QL_OS.MACOS]):
108+
def convert_path(self, rootfs: Union[str, Path], cwd: str, path: str) -> Path:
109+
emulated_os = self.ql.ostype
110+
hosting_os = self.ql.platform
111+
112+
# emulated os and hosting platform are of the same type
113+
if (emulated_os == hosting_os) or (emulated_os in QL_OS_POSIX and hosting_os in QL_OS_POSIX):
120114
return QlPathManager.convert_for_native_os(rootfs, cwd, path)
121-
elif self.ql.ostype in [QL_OS.LINUX, QL_OS.MACOS] and self.ql.platform == QL_OS.WINDOWS:
115+
116+
elif emulated_os in QL_OS_POSIX and hosting_os == QL_OS.WINDOWS:
122117
return QlPathManager.convert_posix_to_win32(rootfs, cwd, path)
123-
elif self.ql.ostype == QL_OS.WINDOWS and self.ql.platform in [QL_OS.LINUX, QL_OS.MACOS]:
118+
119+
elif emulated_os == QL_OS.WINDOWS and hosting_os in QL_OS_POSIX:
124120
return QlPathManager.convert_win32_to_posix(rootfs, cwd, path)
121+
125122
else:
126-
# Fallback
127123
return QlPathManager.convert_for_native_os(rootfs, cwd, path)
128-
129-
def transform_to_link_path(self, path):
130-
rootfs = self.ql.rootfs
131-
real_path = self.convert_path(rootfs, self.cwd, path)
124+
125+
def transform_to_link_path(self, path: str) -> str:
126+
real_path = self.convert_path(self.ql.rootfs, self.cwd, path)
132127

133128
return str(real_path.absolute())
134129

135-
def transform_to_real_path(self, path):
136-
from types import FunctionType
130+
def transform_to_real_path(self, path: str) -> str:
131+
real_path = self.convert_path(self.ql.rootfs, self.cwd, path)
137132

138-
rootfs = self.ql.rootfs
139-
real_path = self.convert_path(rootfs, self.cwd, path)
140-
141133
if os.path.islink(real_path):
142134
link_path = Path(os.readlink(real_path))
135+
143136
if not link_path.is_absolute():
144137
real_path = Path(os.path.join(os.path.dirname(real_path), link_path))
145138

146139
# resolve multilevel symbolic link
147140
if not os.path.exists(real_path):
148141
path_dirs = link_path.parts
142+
149143
if link_path.is_absolute():
150144
path_dirs = path_dirs[1:]
151145

152-
for i in range(0, len(path_dirs)-1):
146+
for i in range(len(path_dirs) - 1):
153147
path_prefix = os.path.sep.join(path_dirs[:i+1])
154148
real_path_prefix = self.transform_to_real_path(path_prefix)
155149
path_remain = os.path.sep.join(path_dirs[i+1:])
156150
real_path = Path(os.path.join(real_path_prefix, path_remain))
151+
157152
if os.path.exists(real_path):
158153
break
159-
154+
160155
return str(real_path.absolute())
161156

162157
# The `relative path` here refers to the path which is relative to the rootfs.
163-
def transform_to_relative_path(self, path):
158+
def transform_to_relative_path(self, path: str) -> str:
164159
return str(Path(self.cwd) / path)

0 commit comments

Comments
 (0)