mirror of
https://github.com/qilingframework/qiling.git
synced 2026-10-12 02:21:40 +00:00
Opportunistic PEP8 fixes
This commit is contained in:
@@ -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
|
||||
|
||||
+28
-12
@@ -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']
|
||||
|
||||
+39
-18
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user