Source code for qbindiff.loader.backend.abstract
# Copyright 2023 Quarkslab
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Interface of a backend loader
"""
from __future__ import annotations
import networkx
from abc import ABCMeta, abstractmethod
from qbindiff.loader import Structure
from qbindiff.loader.types import (
FunctionType,
ReferenceType,
ReferenceTarget,
OperandType,
ProgramCapability,
)
from qbindiff.types import Addr
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from pypcode import PcodeOp
from collections.abc import Iterator
from qbindiff.loader.types import InstructionGroup
[docs]
class AbstractOperandBackend(metaclass=ABCMeta):
"""
This is an abstract class and should not be used as is.
It represents a generic backend loader for a Operand
"""
@abstractmethod
def __str__(self) -> str:
raise NotImplementedError()
@property
@abstractmethod
def value(self) -> int | None:
"""
Returns the immediate value (not addresses) if the operand is constant.
If not, None is returned.
"""
raise NotImplementedError()
@property
@abstractmethod
def type(self) -> OperandType:
"""
Returns the operand type.
"""
raise NotImplementedError()
[docs]
class AbstractInstructionBackend(metaclass=ABCMeta):
"""
This is an abstract class and should not be used as is.
It represents a generic backend loader for a Instruction
"""
#: Max instruction ID. All the instruction IDs will be in the range [0, MAX_ID]
MAX_ID = 3000
@property
@abstractmethod
def addr(self) -> Addr:
"""
The address of the instruction
"""
raise NotImplementedError()
@property
@abstractmethod
def mnemonic(self) -> str:
"""
Returns the instruction mnemonic as a string
"""
raise NotImplementedError()
@property
@abstractmethod
def references(self) -> dict[ReferenceType, list[ReferenceTarget]]:
"""
Returns all the references towards the instruction
"""
raise NotImplementedError()
@property
@abstractmethod
def operands(self) -> Iterator[AbstractOperandBackend]:
"""
Returns an iterator over backend operand objects
"""
raise NotImplementedError()
@property
@abstractmethod
def id(self) -> int:
"""
Returns the instruction ID as a non negative int. The ID is in the range [0, MAX_ID].
The value MAX_ID means that there is no ID available.
.. warning::
The backend is responsible for creating this value, different backends
should not be considered compatible between each other. (For example IDA
relies on IDA IDs while quokka relies on capstone IDs)
"""
raise NotImplementedError()
@property
@abstractmethod
def comment(self) -> str:
"""
Comment associated with the instruction
"""
raise NotImplementedError()
@property
@abstractmethod
def bytes(self) -> bytes:
"""
Returns the bytes representation of the instruction
"""
raise NotImplementedError()
@property
def groups(self) -> list[InstructionGroup]:
"""
Returns a list of groups of this instruction.
Provided with the INSTR_GROUP capability
"""
raise NotImplementedError()
@property
def pcode_ops(self) -> list[PcodeOp]:
"""
List of PcodeOp associated with the instruction.
Provided with the PCODE capability
"""
raise NotImplementedError()
[docs]
class AbstractBasicBlockBackend(metaclass=ABCMeta):
"""
This is an abstract class and should not be used as is.
It represents a generic backend loader for a BasicBlock
"""
@abstractmethod
def __len__(self) -> int:
"""
The numbers of instructions in the basic block
"""
raise NotImplementedError()
@property
@abstractmethod
def addr(self) -> Addr:
"""
The address of the basic block
"""
raise NotImplementedError()
@property
@abstractmethod
def instructions(self) -> Iterator[AbstractInstructionBackend]:
"""
Returns an iterator over backend instruction objects
"""
raise NotImplementedError()
@property
@abstractmethod
def bytes(self) -> bytes:
"""
Returns the bytes representation of the basic block
"""
raise NotImplementedError()
[docs]
class AbstractFunctionBackend(metaclass=ABCMeta):
"""
This is an abstract class and should not be used as is.
It represents a generic backend loader for a Function.
"""
@property
@abstractmethod
def basic_blocks(self) -> Iterator[AbstractBasicBlockBackend]:
"""
Returns an iterator over backend basic blocks objects.
"""
raise NotImplementedError()
@property
@abstractmethod
def addr(self) -> Addr:
"""
The address of the function.
"""
raise NotImplementedError()
@property
@abstractmethod
def graph(self) -> networkx.DiGraph:
"""
The Control Flow Graph of the function.
"""
raise NotImplementedError()
@property
@abstractmethod
def parents(self) -> set[Addr]:
"""
Set of function parents in the call graph.
"""
raise NotImplementedError()
@property
@abstractmethod
def children(self) -> set[Addr]:
"""
Set of function children in the call graph.
"""
raise NotImplementedError()
@property
@abstractmethod
def type(self) -> FunctionType:
"""
The type of the function.
"""
raise NotImplementedError()
@property
@abstractmethod
def name(self) -> str:
"""
The name of the function.
"""
raise NotImplementedError()
[docs]
def unload_blocks(self) -> None:
"""
Unload basic blocks from memory
"""
pass
[docs]
class AbstractProgramBackend(metaclass=ABCMeta):
"""
This is an abstract class and should not be used as is.
It represents a generic backend loader for a Program
"""
@property
@abstractmethod
def functions(self) -> Iterator[AbstractFunctionBackend]:
"""
Returns an iterator over backend function objects.
"""
raise NotImplementedError()
@property
@abstractmethod
def name(self) -> str:
"""
The name of the program.
"""
raise NotImplementedError()
@property
@abstractmethod
def structures(self) -> list[Structure]:
"""
Returns the list of structures defined in program.
"""
raise NotImplementedError()
@property
@abstractmethod
def callgraph(self) -> networkx.DiGraph:
"""
The callgraph of the program.
"""
raise NotImplementedError()
@property
@abstractmethod
def fun_names(self) -> dict[str, Addr]:
"""
Returns a dictionary with function name as key and the function address as value.
"""
raise NotImplementedError()
@property
@abstractmethod
def exec_path(self) -> str:
"""
Returns the executable path
"""
raise NotImplementedError()
@property
def capabilities(self) -> ProgramCapability:
"""
Returns the supported capabilities
"""
return ProgramCapability(0)