diff --git a/src/elf_diff/__main__.py b/src/elf_diff/__main__.py index e051d6e0..27213690 100644 --- a/src/elf_diff/__main__.py +++ b/src/elf_diff/__main__.py @@ -133,6 +133,8 @@ def main(): except Exception as exception: if settings is not None: errorOutput(settings, exception, force_stacktrace=True) + else: + print(f"Error: {exception}") sys.exit(RETURN_CODE_UNRECOVERABLE_ERROR) else: print(f"{CHECKERED_FLAG} Done.") diff --git a/src/elf_diff/default_plugins.py b/src/elf_diff/default_plugins.py index 8ef56b8f..94432eff 100644 --- a/src/elf_diff/default_plugins.py +++ b/src/elf_diff/default_plugins.py @@ -29,7 +29,10 @@ from elf_diff.plugins.export.pdf.plugin import PDFExportPairReportPlugin from elf_diff.plugins.export.yaml.plugin import YAMLExportPairReportPlugin from elf_diff.plugins.export.json.plugin import JSONExportPairReportPlugin -from elf_diff.plugins.export.txt.plugin import TXTExportPairReportPlugin +from elf_diff.plugins.export.txt.plugin import ( + TXTExportPairReportPlugin, + TXTExportStatisticsPlugin, +) from elf_diff.plugins.export.xml.plugin import XMLExportPairReportPlugin from elf_diff.settings import Settings from typing import Dict, Type, List @@ -40,6 +43,7 @@ "yaml_export": YAMLExportPairReportPlugin, "json_export": JSONExportPairReportPlugin, "txt_export": TXTExportPairReportPlugin, + "stats_txt_export": TXTExportStatisticsPlugin, "xml_export": XMLExportPairReportPlugin, } @@ -91,6 +95,10 @@ def activateDefaultPlugins(settings: Settings) -> None: plugin_configuration = {"output_file": settings.txt_file} activateDefaultPlugin(settings, TXTExportPairReportPlugin, plugin_configuration) + if settings.stats_txt_file: + plugin_configuration = {"output_file": settings.stats_txt_file} + activateDefaultPlugin(settings, TXTExportStatisticsPlugin, plugin_configuration) + if settings.xml_file: plugin_configuration = {"output_file": settings.xml_file} activateDefaultPlugin(settings, XMLExportPairReportPlugin, plugin_configuration) diff --git a/src/elf_diff/plugins/export/txt/plugin.py b/src/elf_diff/plugins/export/txt/plugin.py index 2c15089a..f3c5a94f 100644 --- a/src/elf_diff/plugins/export/txt/plugin.py +++ b/src/elf_diff/plugins/export/txt/plugin.py @@ -59,3 +59,62 @@ def getConfigurationInformation() -> PluginConfigurationInformation: return [PluginConfigurationKey("output_file", "The text output file")] + super( TXTExportPairReportPlugin, TXTExportPairReportPlugin ).getConfigurationInformation() + + +class TXTExportStatisticsPlugin(ExportPairReportPlugin): + """A plugin class that exports statistics about the difference of two elf files as a text file""" + + def __init__(self, settings: Settings, plugin_configuration: Dict[str, str]): + super().__init__(settings, plugin_configuration) + + def export(self, document: ValueTreeNode): + files_differ = ( + (document.statistics.overall.delta.resource_consumption.code != 0) + or (document.statistics.overall.delta.resource_consumption.text != 0) + or (document.statistics.overall.delta.resource_consumption.data != 0) + or (document.statistics.overall.delta.resource_consumption.static_ram != 0) + or (document.statistics.overall.delta.resource_consumption.bss != 0) + or (len(document.symbols.disappeared) > 0) + or (len(document.symbols.appeared) > 0) + or (len(document.symbols.similar) > 0) + or (len(document.symbols.migrated) > 0) + ) + + with open(self.getConfigurationParameter("output_file"), "w") as f: + f.write( + f"""\ +Statistics of elf_diff comparison of files + old: {document.files.input.old.binary_path} + new: {document.files.input.new.binary_path} + +Difference in resource consumption: + code: {document.statistics.overall.delta.resource_consumption.code} bytes + text: {document.statistics.overall.delta.resource_consumption.text} bytes + data: {document.statistics.overall.delta.resource_consumption.data} bytes + static ram: {document.statistics.overall.delta.resource_consumption.static_ram} bytes + bss: {document.statistics.overall.delta.resource_consumption.bss} bytes + +Symbol statistics: + old: {len(document.symbols.old)} + new: {len(document.symbols.new)} + persisting: {len(document.symbols.persisting)} + disappeared: {len(document.symbols.disappeared)} + appeared: {len(document.symbols.appeared)} + similar: {len(document.symbols.similar)} + migrated: {len(document.symbols.migrated)} + +""" + ) + if not files_differ: + f.write("No significant differences.") + else: + f.write("Files differ.") + + @staticmethod + def getConfigurationInformation() -> PluginConfigurationInformation: + """Return plugin configuration information""" + return [ + PluginConfigurationKey("output_file", "The statistics text output file") + ] + super( + TXTExportStatisticsPlugin, TXTExportStatisticsPlugin + ).getConfigurationInformation() diff --git a/src/elf_diff/settings.py b/src/elf_diff/settings.py index 4b24352b..c8a8b8d7 100644 --- a/src/elf_diff/settings.py +++ b/src/elf_diff/settings.py @@ -187,6 +187,9 @@ def __init__( Parameter("yaml_file", "The filename of the generated YAML report."), Parameter("json_file", "The filename of the generated JSON report."), Parameter("txt_file", "The filename of the generated text based report."), + Parameter( + "stats_txt_file", "The filename of the generated statistics text file." + ), Parameter("xml_file", "The filename of the generated XML report."), Parameter( "dump_document_structure", @@ -304,6 +307,7 @@ def __init__(self, module_path): self.yaml_file: str self.json_file: str self.txt_file: str + self.stats_txt_file: str self.xml_file: str self.project_title: str self.driver_file: str diff --git a/tests/test_cases/test_command_line_args.py b/tests/test_cases/test_command_line_args.py index 67e96a5a..a14d364a 100644 --- a/tests/test_cases/test_command_line_args.py +++ b/tests/test_cases/test_command_line_args.py @@ -402,6 +402,9 @@ def test_symbol_selection_regex_new(self): def test_symbol_selection_regex_old(self): self.runSimpleTest2([("symbol_selection_regex_old", ".*IStay.*")]) + def test_stats_txt_file(self): + self.runSimpleTest([("stats_txt_file", "stats.txt")]) + def test_txt_file(self): self.runSimpleTest([("txt_file", "output.txt")])