From 609ea313be41df516f799fb9788cbfc5a7631704 Mon Sep 17 00:00:00 2001 From: elicn Date: Fri, 14 Apr 2023 15:08:06 +0300 Subject: [PATCH] Opportunistic PEP8 fixes --- qiling/loader/loader.py | 4 ++- qiling/log.py | 40 ++++++++++++++++++++--------- qiling/utils.py | 57 ++++++++++++++++++++++++++++------------- 3 files changed, 70 insertions(+), 31 deletions(-) diff --git a/qiling/loader/loader.py b/qiling/loader/loader.py index 6be0ccf1..3ad3a3d7 100644 --- a/qiling/loader/loader.py +++ b/qiling/loader/loader.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -8,11 +8,13 @@ from typing import Any, Mapping, MutableSequence, NamedTuple, Optional from qiling import Qiling + class Image(NamedTuple): base: int end: int path: str + class QlLoader: def __init__(self, ql: Qiling): self.ql = ql diff --git a/qiling/log.py b/qiling/log.py index d085266e..46026b8d 100644 --- a/qiling/log.py +++ b/qiling/log.py @@ -3,20 +3,28 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # +from __future__ import annotations + import copy import logging import os import re import weakref -from typing import Optional, TextIO +from typing import TYPE_CHECKING, Optional, TextIO +from logging import Filter, Formatter, LogRecord, Logger, NullHandler, StreamHandler, FileHandler from qiling.const import QL_VERBOSE +if TYPE_CHECKING: + from qiling import Qiling + + QL_INSTANCE_ID = 114514 FMT_STR = '%(levelname)s\t%(message)s' + class COLOR: WHITE = '\033[37m' CRIMSON = '\033[31m' @@ -28,7 +36,8 @@ class COLOR: CYAN = '\033[96m' ENDC = '\033[0m' -class QlBaseFormatter(logging.Formatter): + +class QlBaseFormatter(Formatter): __level_tag = { 'WARNING' : '[!]', 'INFO' : '[=]', @@ -37,7 +46,7 @@ class QlBaseFormatter(logging.Formatter): 'ERROR' : '[x]' } - def __init__(self, ql, *args, **kwargs): + def __init__(self, ql: Qiling, *args, **kwargs): super().__init__(*args, **kwargs) self.ql = weakref.proxy(ql) @@ -47,7 +56,7 @@ class QlBaseFormatter(logging.Formatter): def get_thread_tag(self, thread: str) -> str: return thread - def format(self, record: logging.LogRecord): + def format(self, record: LogRecord): # In case we have multiple formatters, we have to keep a copy of the record. record = copy.copy(record) @@ -64,6 +73,7 @@ class QlBaseFormatter(logging.Formatter): return super().format(record) + class QlColoredFormatter(QlBaseFormatter): __level_color = { 'WARNING' : COLOR.YELLOW, @@ -83,15 +93,17 @@ class QlColoredFormatter(QlBaseFormatter): return f'{COLOR.GREEN}{s}{COLOR.ENDC}' -class RegexFilter(logging.Filter): + +class RegexFilter(Filter): def update_filter(self, regexp: str): self._filter = re.compile(regexp) - def filter(self, record: logging.LogRecord): + def filter(self, record: LogRecord): msg = record.getMessage() return self._filter.match(msg) is not None + def resolve_logger_level(verbose: QL_VERBOSE) -> int: return { QL_VERBOSE.DISABLED : logging.CRITICAL, @@ -102,6 +114,7 @@ def resolve_logger_level(verbose: QL_VERBOSE) -> int: QL_VERBOSE.DUMP : logging.DEBUG }[verbose] + def __is_color_terminal(stream: TextIO) -> bool: """Determine whether standard output is attached to a color terminal. @@ -142,7 +155,8 @@ def __is_color_terminal(stream: TextIO) -> bool: return handler(stream.fileno()) -def setup_logger(ql, log_file: Optional[str], console: bool, log_override: Optional[logging.Logger], log_plain: bool): + +def setup_logger(ql: Qiling, log_file: Optional[str], console: bool, log_override: Optional[Logger], log_plain: bool): global QL_INSTANCE_ID # If there is an override for our logger, then use it. @@ -155,13 +169,14 @@ def setup_logger(ql, log_file: Optional[str], console: bool, log_override: Optio # Disable propagation to avoid duplicate output. log.propagate = False + # Clear all handlers and filters. - log.handlers = [] - log.filters = [] + log.handlers.clear() + log.filters.clear() # Do we have console output? if console: - handler = logging.StreamHandler() + handler = StreamHandler() if log_plain or not __is_color_terminal(handler.stream): formatter = QlBaseFormatter(ql, FMT_STR) @@ -171,12 +186,12 @@ def setup_logger(ql, log_file: Optional[str], console: bool, log_override: Optio handler.setFormatter(formatter) log.addHandler(handler) else: - handler = logging.NullHandler() + handler = NullHandler() log.addHandler(handler) # Do we have to write log to a file? if log_file is not None: - handler = logging.FileHandler(log_file) + handler = FileHandler(log_file) formatter = QlBaseFormatter(ql, FMT_STR) handler.setFormatter(formatter) log.addHandler(handler) @@ -185,4 +200,5 @@ def setup_logger(ql, log_file: Optional[str], console: bool, log_override: Optio return log + __all__ = ['RegexFilter', 'setup_logger', 'resolve_logger_level'] diff --git a/qiling/utils.py b/qiling/utils.py index ccdd970e..05cb0a43 100644 --- a/qiling/utils.py +++ b/qiling/utils.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -8,11 +8,13 @@ This module is intended for general purpose functions that can be used thoughout the qiling framework """ -from functools import partial -from pathlib import Path -import importlib, inspect, os +import importlib +import inspect +import os +from functools import partial from configparser import ConfigParser +from pathlib import Path from types import ModuleType from typing import TYPE_CHECKING, Any, Callable, Mapping, Optional, Tuple, TypeVar, Union @@ -38,27 +40,32 @@ def __name_to_enum(name: str, mapping: Mapping[str, T], aliases: Mapping[str, st return mapping.get(aliases.get(key) or key) + def os_convert(os: str) -> Optional[QL_OS]: alias_map = { - 'darwin' : 'macos' + 'darwin': 'macos' } return __name_to_enum(os, os_map, alias_map) + def arch_convert(arch: str) -> Optional[QL_ARCH]: alias_map = { - 'x86_64' : 'x8664', - 'riscv32' : 'riscv' + 'x86_64': 'x8664', + 'riscv32': 'riscv' } return __name_to_enum(arch, arch_map, alias_map) + def debugger_convert(debugger: str) -> Optional[QL_DEBUGGER]: return __name_to_enum(debugger, debugger_map) + def arch_os_convert(arch: QL_ARCH) -> Optional[QL_OS]: return arch_os_map.get(arch) + def ql_get_module(module_name: str) -> ModuleType: try: module = importlib.import_module(module_name, 'qiling') @@ -67,6 +74,7 @@ def ql_get_module(module_name: str) -> ModuleType: return module + def ql_get_module_function(module_name: str, member_name: str): module = ql_get_module(module_name) @@ -77,6 +85,7 @@ def ql_get_module_function(module_name: str, member_name: str): return member + def __emu_env_from_pathname(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], Optional[QL_ENDIAN]]: if os.path.isdir(path) and path.endswith('.kext'): return QL_ARCH.X8664, QL_OS.MACOS, QL_ENDIAN.EL @@ -89,6 +98,7 @@ def __emu_env_from_pathname(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_O return None, None, None + def __emu_env_from_elf(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], Optional[QL_ENDIAN]]: # instead of using full-blown elffile parsing, we perform a simple parsing to avoid # external dependencies for target systems that do not need them. @@ -99,7 +109,7 @@ def __emu_env_from_elf(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], O ELFCLASS32 = 1 # 32-bit ELFCLASS64 = 2 # 64-bit - #ei_data + # ei_data ELFDATA2LSB = 1 # little-endian ELFDATA2MSB = 2 # big-endian @@ -121,8 +131,8 @@ def __emu_env_from_elf(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], O EM_PPC = 20 endianess = { - ELFDATA2LSB : (QL_ENDIAN.EL, 'little'), - ELFDATA2MSB : (QL_ENDIAN.EB, 'big') + ELFDATA2LSB: (QL_ENDIAN.EL, 'little'), + ELFDATA2MSB: (QL_ENDIAN.EB, 'big') } machines32 = { @@ -140,8 +150,8 @@ def __emu_env_from_elf(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], O } classes = { - ELFCLASS32 : machines32, - ELFCLASS64 : machines64 + ELFCLASS32: machines32, + ELFCLASS64: machines64 } abis = { @@ -192,6 +202,7 @@ def __emu_env_from_elf(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], O return archtype, ostype, archendian + def __emu_env_from_macho(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], Optional[QL_ENDIAN]]: macho_macos_sig64 = b'\xcf\xfa\xed\xfe' macho_macos_sig32 = b'\xce\xfa\xed\xfe' @@ -220,6 +231,7 @@ def __emu_env_from_macho(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], return arch, ostype, endian + def __emu_env_from_pe(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], Optional[QL_ENDIAN]]: import pefile @@ -260,6 +272,7 @@ def __emu_env_from_pe(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], Op return arch, ostype, archendian + def ql_guess_emu_env(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], Optional[QL_ENDIAN]]: guessing_methods = ( __emu_env_from_pathname, @@ -278,9 +291,10 @@ def ql_guess_emu_env(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS], Opt return arch, ostype, endian + def select_loader(ostype: QL_OS, libcache: bool) -> QlClassInit['QlLoader']: if ostype == QL_OS.WINDOWS: - kwargs = {'libcache' : libcache} + kwargs = {'libcache': libcache} else: kwargs = {} @@ -305,6 +319,7 @@ def select_loader(ostype: QL_OS, libcache: bool) -> QlClassInit['QlLoader']: return partial(obj, **kwargs) + def select_component(component_type: str, component_name: str, **kwargs) -> QlClassInit[Any]: component_path = f'.{component_type}.{component_name}' component_class = f'Ql{component_name.capitalize()}Manager' @@ -313,6 +328,7 @@ def select_component(component_type: str, component_name: str, **kwargs) -> QlCl return partial(obj, **kwargs) + def select_debugger(options: Union[str, bool]) -> Optional[QlClassInit['QlDebugger']]: if options is True: options = 'gdb' @@ -353,14 +369,15 @@ def select_debugger(options: Union[str, bool]) -> Optional[QlClassInit['QlDebugg return None + def select_arch(archtype: QL_ARCH, endian: QL_ENDIAN, thumb: bool) -> QlClassInit['QlArch']: # set endianess and thumb mode for arm-based archs - if archtype == QL_ARCH.ARM: - kwargs = {'endian' : endian, 'thumb' : thumb} + if archtype is QL_ARCH.ARM: + kwargs = {'endian': endian, 'thumb': thumb} # set endianess for mips arch - elif archtype == QL_ARCH.MIPS: - kwargs = {'endian' : endian} + elif archtype is QL_ARCH.MIPS: + kwargs = {'endian': endian} else: kwargs = {} @@ -386,6 +403,7 @@ def select_arch(archtype: QL_ARCH, endian: QL_ENDIAN, thumb: bool) -> QlClassIni return partial(obj, **kwargs) + def select_os(ostype: QL_OS) -> QlClassInit['QlOs']: qlos_name = ostype.name qlos_path = f'.os.{qlos_name.lower()}.{qlos_name.lower()}' @@ -395,9 +413,10 @@ def select_os(ostype: QL_OS) -> QlClassInit['QlOs']: return partial(obj) + def profile_setup(ostype: QL_OS, user_config: Optional[Union[str, dict]]): # mcu uses a yaml-based config - if ostype == QL_OS.MCU: + if ostype is QL_OS.MCU: import yaml if user_config: @@ -426,6 +445,7 @@ def profile_setup(ostype: QL_OS, user_config: Optional[Union[str, dict]]): return config + # verify if emulator returns properly def verify_ret(ql: 'Qiling', err): # init_sp location is not consistent; this is here to work around that @@ -463,6 +483,7 @@ def verify_ret(ql: 'Qiling', err): else: raise + __all__ = [ 'os_convert', 'arch_convert',