diff --git a/s2e_env/command.py b/s2e_env/command.py index 80afe1e8..9928bed5 100644 --- a/s2e_env/command.py +++ b/s2e_env/command.py @@ -30,6 +30,7 @@ """ +from abc import ABCMeta, abstractmethod from argparse import ArgumentParser import json import logging @@ -102,6 +103,9 @@ class BaseCommand(object): ``help`` class attribute should be specified. """ + # Abstract class + __metaclass__ = ABCMeta + # Metadata about this command help = '' @@ -183,6 +187,7 @@ def execute(self, *args, **options): def name(self): return self.__module__.split('.')[-1] + @abstractmethod def handle(self, *args, **options): """ The actual logic of the command. Subclasses must implement this method. diff --git a/s2e_env/commands/code_coverage/basic_block.py b/s2e_env/commands/code_coverage/basic_block.py index 43ca3ce4..15b2238f 100644 --- a/s2e_env/commands/code_coverage/basic_block.py +++ b/s2e_env/commands/code_coverage/basic_block.py @@ -23,6 +23,7 @@ from __future__ import division +from abc import abstractmethod from collections import defaultdict import json import itertools @@ -276,6 +277,7 @@ def _initialize_disassembler(self): """ pass + @abstractmethod def _get_disassembly_info(self, module_path): """ Disassemble the give module using on the of the supported backends (IDA diff --git a/s2e_env/commands/coverage.py b/s2e_env/commands/coverage.py index 88da1b5c..86b88705 100644 --- a/s2e_env/commands/coverage.py +++ b/s2e_env/commands/coverage.py @@ -22,7 +22,6 @@ from s2e_env.command import ProjectCommand, CommandError -from s2e_env.commands.code_coverage.basic_block import BasicBlockCoverage from s2e_env.commands.code_coverage.lcov import LineCoverage from s2e_env.manage import call_command @@ -62,7 +61,7 @@ def add_arguments(self, parser): help='Where to store the LCOV report (by default into s2e-last)', required=False) - bb_parser = subparsers.add_parser('basic_block', cmd=BasicBlockCoverage(), + bb_parser = subparsers.add_parser('basic_block', cmd=IDABasicBlockCoverage(), help='Generate a basic block report') bb_parser.add_argument('-d', '--disassembler', choices=('ida', 'r2', 'binaryninja'), default='ida', help='Disassembler backend to use') diff --git a/s2e_env/commands/project_creation/abstract_project.py b/s2e_env/commands/project_creation/abstract_project.py index f09dae6a..dd6b7a8f 100644 --- a/s2e_env/commands/project_creation/abstract_project.py +++ b/s2e_env/commands/project_creation/abstract_project.py @@ -23,6 +23,7 @@ """ +from abc import abstractmethod import logging import os import shutil @@ -72,6 +73,7 @@ def handle(self, *args, **options): # Abstract methods to overwrite # + @abstractmethod def _configure(self, target, *args, **kwargs): """ Generate the configuration dictionary that describes this project. @@ -86,6 +88,7 @@ def _configure(self, target, *args, **kwargs): raise NotImplementedError('Subclasses of AbstractProject must provide ' 'a _configure method') + @abstractmethod def _create(self, config, force=False): """ Create the actual project based on the given project configuration diff --git a/s2e_env/execution_trace/trace_entries.py b/s2e_env/execution_trace/trace_entries.py index 1540047d..92520ee9 100644 --- a/s2e_env/execution_trace/trace_entries.py +++ b/s2e_env/execution_trace/trace_entries.py @@ -20,6 +20,8 @@ SOFTWARE. """ + +from abc import ABCMeta, abstractmethod import binascii import logging import re @@ -104,6 +106,9 @@ class TraceEntry(object): run-time size of the item **must** be provided. """ + # Abstract method + __metaclass__ = ABCMeta + FORMAT = None def __init__(self, fmt=''): @@ -158,6 +163,7 @@ def deserialize(cls, data, size=None): # pylint: disable=unused-argument except struct.error: raise TraceEntryError('Cannot deserialize %s data' % cls.__name__) + @abstractmethod def serialize(self): """ Serializes the object using the given ``_struct`` property. The user diff --git a/s2e_env/symbols/__init__.py b/s2e_env/symbols/__init__.py index f39d74c1..6ccdd86e 100644 --- a/s2e_env/symbols/__init__.py +++ b/s2e_env/symbols/__init__.py @@ -20,6 +20,8 @@ SOFTWARE. """ + +from abc import ABCMeta, abstractmethod import json import logging import os @@ -43,6 +45,9 @@ class DebugInfo(object): It must be subclassed to handle specific formats (ELF, PE, etc.). """ + # Abstract class + __metaclass__ = ABCMeta + def __init__(self, path, search_paths=None): self._path = path self._search_paths = search_paths @@ -94,6 +99,7 @@ def get_coverage(self, addr_counts, include_covered_files_only=False): return file_line_info + @abstractmethod def parse(self): """ To be implemented by clients