64 lines
1.8 KiB
Python
64 lines
1.8 KiB
Python
|
#!/usr/bin/env python3
|
||
|
#
|
||
|
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
|
||
|
#
|
||
|
|
||
|
from __future__ import annotations
|
||
|
|
||
|
import os
|
||
|
from typing import TYPE_CHECKING, Any, Mapping, MutableSequence, NamedTuple, Optional
|
||
|
|
||
|
if TYPE_CHECKING:
|
||
|
from qiling import Qiling
|
||
|
|
||
|
|
||
|
class Image(NamedTuple):
|
||
|
base: int
|
||
|
end: int
|
||
|
path: str
|
||
|
|
||
|
|
||
|
class QlLoader:
|
||
|
def __init__(self, ql: Qiling):
|
||
|
self.ql = ql
|
||
|
self.env = self.ql.env
|
||
|
self.argv = self.ql.argv
|
||
|
self.images: MutableSequence[Image] = []
|
||
|
self.skip_exit_check = False
|
||
|
|
||
|
def find_containing_image(self, address: int) -> Optional[Image]:
|
||
|
"""Retrieve the image object that contains the specified address.
|
||
|
|
||
|
Returns: image containing the specified address, or `None` if not found
|
||
|
"""
|
||
|
|
||
|
return next((image for image in self.images if image.base <= address < image.end), None)
|
||
|
|
||
|
def get_image_by_name(self, name: str, *, casefold: bool = False) -> Optional[Image]:
|
||
|
"""Retrieve an image by its basename.
|
||
|
|
||
|
Args:
|
||
|
name : image base name
|
||
|
casefold : whether name matching should be case-insensitive (default is case-sensitive)
|
||
|
|
||
|
Returns: image object whose basename match to the one given, or `None` if not found
|
||
|
"""
|
||
|
|
||
|
cf = str.casefold if casefold else lambda s: s
|
||
|
|
||
|
return next((image for image in self.images if cf(os.path.basename(image.path)) == cf(name)), None)
|
||
|
|
||
|
def save(self) -> Mapping[str, Any]:
|
||
|
saved_state = {
|
||
|
'images': [tuple(img) for img in self.images]
|
||
|
}
|
||
|
|
||
|
return saved_state
|
||
|
|
||
|
def restore(self, saved_state: Mapping[str, Any]):
|
||
|
self.images = [Image(*img) for img in saved_state['images']]
|
||
|
|
||
|
# loader main method; derivatives must implement one of their own
|
||
|
def run(self) -> None:
|
||
|
raise NotImplementedError
|