Hani Saleh

144 papers A 1B 1C 24Journal 56Unranked 60
YearRankTypeTitle / Venue / Authors
2025 C conf
ISCAS
Vasilis Sakellariou, Vassilis Paliouras, Ioannis Kouretas, Hani Saleh, Thanos Stouraitis
2025 J jnl
Proc. IEEE
Ghada Alsuhli, Vasilis Sakellariou, Hani Saleh, Mahmoud Al-Qutayri, Baker Mohammad, Thanos Stouraitis
2025 J jnl
IEEE Trans. Emerg. Top. Comput.
Ghada Alsuhli, Hani Saleh, Mahmoud Al-Qutayri, Baker Mohammad, Thanos Stouraitis
2025 J jnl
CoRR
Binke Zhao, Ghada Alsuhli, Hani Saleh, Baker Mohammad
2025 J jnl
Eng. Appl. Artif. Intell.
Adil Rehman, Mostafa Moussa, Hani Saleh, Ali Khraibi, Ahsan H. Khandoker
2025 J jnl
J. Inf. Secur. Appl.
Ghada Alsuhli, Hani Saleh, Mahmoud Al-Qutayri, Baker Mohammad, Thanos Stouraitis
2025 J jnl
IEEE Trans. Artif. Intell.
Ghadeer A. Jaradat, Mohamed F. Tolba, Ghada Alsuhli, Hani Saleh, Mahmoud Al-Qutayri, Thanos Stouraitis
2025 J jnl
Comput. Secur.
Raviha Khan, Hossien B. Eldeeb, Brahim Mefgouda, Omar Alhussein, Hani Saleh, Sami Muhaidat
2025 C conf
ISCAS
Mohammed F. Tolba, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri, Thanos Stouraitis
2025 J jnl
IEEE Trans. Circuits Syst. Artif. Intell.
Huruy Tesfai, Leen Younes, Hani Saleh, Mahmoud Al-Qutayri, Baker Mohammad
2025 conf
NewCAS
Adil Rehman, Mohamed F. Tolba, Hani Saleh, Ahsan Khandoker, Mahmoud Al-Qutayri
2025 J jnl
Comput. Biol. Medicine
Adil Rehman, Hani Saleh
2024 J jnl
IEEE Trans. Emerg. Top. Comput.
Vasilis Sakellariou, Vassilis Paliouras, Ioannis Kouretas, Hani Saleh, Thanos Stouraitis
2024 conf
AICAS
Meriem Bettayeb, Eman Hassan, Muhammad Umair Khan, Yasmin Halawani, Hani Saleh, Baker Mohammad
2024 conf
AICAS
Vasilis Sakellariou, Vassilis Paliouras, Ioannis Kouretas, Hani Saleh, Thanos Stouraitis
2024 conf
EMBC
Adil Rehman, Mostafa Moussa, Hani Saleh, Naoufel Werghi, Ali Khraibi, Ahsan Khandoker
2024 J jnl
IEEE Trans. Inf. Forensics Secur.
Enas E. Abulibdeh, Leen Younes, Baker Mohammad, Khaled Humood, Hani Saleh, Mahmoud Al-Qutayri
2024 J jnl
Internet Things
Eman Hassan, Zhuowen Zou, Hanning Chen, Mohsen Imani, Yahya H. Zweiri, Hani Saleh, Baker Mohammad
2024 J jnl
IEEE Trans. Artif. Intell.
Mohamed F. Tolba, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri, Ayman Hroub, Thanos Stouraitis
2024 J jnl
CoRR
Ghadeer A. Jaradat, Mohammed F. Tolba, Ghada Alsuhli, Hani Saleh, Mahmoud Al-Qutayri, Thanos Stouraitis, Baker Mohammad
2024 conf
GLOBECOM (Workshops)
Brahim Mefgouda, Raviha Khan, Omar Alhussein, Hani Saleh, Hossien B. Eldeeb, Anshul Pandey, Sami Muhaidat
2024 J jnl
CoRR
Brahim Mefgouda, Raviha Khan, Omar Alhussein, Hani Saleh, Hossien B. Eldeeb, Anshul Pandey, Sami Muhaidat
2023 C conf
ARITH
Vasilis Sakellariou, Vassilis Paliouras, Ioannis Kouretas, Hani Saleh, Thanos Stouraitis
2023 conf
ICM
Enas E. Abulibdeh, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri
2023 conf
ICM
Enas E. Abulibdeh, Leen Younes, Baker Mohammad, Hani Saleh, Mahmoud Al-Qutayri, Khaled Humood
2023 C conf
ISCAS
Mohamed F. Tolba, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri, Thanos Stouraitis
2023 conf
ICM
Mohamed F. Tolba, Hani Saleh, Mahmoud Al-Qutayri, Ayman Hroub, Thanos Stouraitis
2023 conf
ICM
Huruy Tekle Tesfai, Hani Saleh, Mahmoud Méribout, Mahmoud Al-Qutayri, Thanos Stouraitis
2023 conf
MWSCAS
Yasmin Halawani, Huruy Tekle Tefai, Baker Mohammad, Hani Saleh
2023 J jnl
IEEE Access
Huruy Tekle Tefai, Hani Saleh, Mahmoud Al-Qutayri, Baker Mohammad, Athanasios Stouraitis
2023 J jnl
IEEE Open J. Commun. Soc.
Tasneem Assaf, Arafat Al-Dweik, Youssef Iraqi, Sobia Jangsher, Anshul Pandey, Jean-Pierre Giacalone, Enas E. Abulibdeh, Hani Saleh, Baker Mohammad
2023 conf
ICM
Eman Hassan, Meriem Bettayeb, Baker Mohammad, Yahya H. Zweiri, Hani Saleh
2023 J jnl
CoRR
Ghada Alsuhli, Vasileios Sakellariou, Hani Saleh, Mahmoud Al-Qutayri, Baker Mohammad, Thanos Stouraitis
2023 conf
ICM
Leen Younes, Baker Mohammad, Mahmoud Al-Qutayri, Hani Saleh, Dima Kilani
2023 conf
AICAS
Meriem Bettayeb, Eman Hassan, Baker Mohammad, Hani Saleh
2022 C conf
ISCAS
Vasilis Sakellariou, Vassilis Paliouras, Ioannis Kouretas, Hani Saleh, Thanos Stouraitis
2022 conf
MWSCAS
Meriem Bettayeb, Huruy Tekle Tesfai, Baker Mohammad, Hani Saleh
2022 conf
ICECS 2022
Biyanu Zerom, Mohamed F. Tolba, Huruy Tekle Tefai, Hani Saleh, Mahmoud Al-Qutayri, Thanos Stouraitis, Baker Mohammad, Ghada Alsuhli
2022 J jnl
IEEE Access
Mohamed F. Tolba, Huruy Tekle Tesfai, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri
2022 J jnl
IEEE Trans. Comput. Aided Des. Integr. Circuits Syst.
Lilas Alrahis, Abhrajit Sengupta, Johann Knechtel, Satwik Patnaik, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri, Ozgur Sinanoglu
2022 J jnl
IEEE Trans. Emerg. Top. Comput.
Lilas Alrahis, Satwik Patnaik, Muhammad Abdullah Hanif, Hani Saleh, Muhammad Shafique, Ozgur Sinanoglu
2022 book
Nourhan Elsayed, Hani Saleh, Baker Mohammad, Mohammed Ismail, Mihai Sanduleanu
2022 J jnl
IEEE Access
Eman Hassan, Yasmin Halawani, Baker Mohammad, Hani Saleh
2022 J jnl
IEEE Access
Huruy Tekle Tefai, Hani Saleh, Mahmoud Al-Qutayri, Moath B. Mohammad, Temesghen Tekeste, Ahsan Khandoker, Baker Mohammad
2022 C conf
ISCAS
Mohammed F. Tolba, Hani Saleh, Mahmoud Al-Qutayri, Baker Mohammad
2021 C conf
ISCAS
Nourhan Elsayed, Hani Saleh, Ademola Mustapha, Baker Mohammad, Mihai Sanduleanu
2021 conf
ICECS
Eman Hassan, Huruy Tekle Tesfai, Baker Mohammad, Hani Saleh
2021 conf
CommNet
Rawan Derbas, Lina Bariah, Sami Muhaidat, Paschalis C. Sofotasios, Hani Saleh, Ernesto Damiani
2021 J jnl
CoRR
Dima Kilani, Baker Mohammad, Yasmin Halawani, Mohammed F. Tolba, Hani Saleh
2021 J jnl
IEEE Access
Dima Kilani, Baker Mohammad, Yasmin Halawani, Mohamed F. Tolba, Hani Saleh
2021 J jnl
IEEE Access
Mohamed F. Tolba, Hani Saleh, Yousuf Al Salami, Mahmoud Al-Qutayri, Baker Mohammad
2021 J jnl
CoRR
Mohammed F. Tolba, Huruy Tekle Tesfai, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri
2021 J jnl
IEEE Access
Yasmin Halawani, Baker Mohammad, Hani Saleh
2021 conf
MWSCAS
Yasmin Halawani, Eman Hassan, Baker Mohammad, Hani Saleh
2021 A conf
DATE
Lilas Alrahis, Satwik Patnaik, Faiq Khalid, Muhammad Abdullah Hanif, Hani Saleh, Muhammad Shafique, Ozgur Sinanoglu
2021 conf
ICECS
Vasilis Sakellariou, Vassilis Paliouras, Ioannis Kouretas, Hani Saleh, Thanos Stouraitis
2021 J jnl
IEEE Trans. Emerg. Top. Comput.
Lilas Alrahis, Muhammad Yasin, Nimisha Limaye, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri, Ozgur Sinanoglu
2021 J jnl
IEEE Trans. Inf. Forensics Secur.
Lilas Alrahis, Satwik Patnaik, Johann Knechtel, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri, Ozgur Sinanoglu
2020 J jnl
IEEE Access
Nourhan Elsayed, Hani Saleh, Baker Mohammad, Mihai Sanduleanu
2020 C conf
ISCAS
Nourhan Elsayed, Hani Saleh, Baker Mohammad, Mihai Sanduleanu
2020 C conf
ISCAS
Huruy Tekle Tefai, Hani Saleh, Temesghen Tekeste, Mahmoud Al-Qutayri, Baker Mohammad
2020 J jnl
IEEE Open J. Commun. Soc.
Maryam Tariq, Arafat Al-Dweik, Baker Mohammad, Hani Saleh, Thanos Stouraitis
2020 J jnl
IEEE Access
Mohamed F. Tolba, Yasmin Halawani, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri
2020 J jnl
CoRR
Lilas Alrahis, Satwik Patnaik, Faiq Khalid, Muhammad Abdullah Hanif, Hani Saleh, Muhammad Shafique, Ozgur Sinanoglu
2020 J jnl
Sensors
Mamady Kebe, Rida Gadhafi, Baker Mohammad, Mihai Sanduleanu, Hani Saleh, Mahmoud Al-Qutayri
2020 book
Dima Kilani, Baker Mohammad, Mohammad Alhawari, Hani Saleh, Mohammed Ismail
2020 J jnl
IEEE Access
Fakhreddine Zayer, Baker Mohammad, Hani Saleh, Gabriele Gianini
2020 J jnl
CoRR
Lilas Alrahis, Satwik Patnaik, Johann Knechtel, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri, Ozgur Sinanoglu
2019 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Abdulqader Nael Mahmoud, Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mohammed Ismail
2019 J jnl
Microelectron. J.
Dima Kilani, Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mihai Sanduleanu, Mohammed Ismail
2019 J jnl
IEEE Access
Mohamed F. Tolba, Wafaa S. Sayed, Mohammed E. Fouda, Hani Saleh, Mahmoud Al-Qutayri, Baker Mohammad, Ahmed G. Radwan
2019 J jnl
Microelectron. J.
Khader Mohammad, Temesghen Tekeste, Baker Mohammad, Hani Saleh, Mahran Qurran
2019 C conf
ISCAS
Lilas Alrahis, Muhammad Yasin, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri
2019 J jnl
IACR Cryptol. ePrint Arch.
Lilas Alrahis, Muhammad Yasin, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri, Ozgur Sinanoglu
2019 J jnl
CoRR
Lilas Alrahis, Muhammad Yasin, Nimisha Limaye, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri, Ozgur Sinanoglu
2019 conf
ASP-DAC
Lilas Alrahis, Muhammad Yasin, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri, Ozgur Sinanoglu
2019 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Temesghen Tekeste, Hani Saleh, Baker Mohammad, Mohammed Ismail
2018 C conf
ISCAS
Abdulqader Nael Mahmoud, Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mohammed Ismail
2018 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Dima Kilani, Baker Mohammad, Mohammad Alhawari, Hani Saleh, Mohammed Ismail
2018 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Temesghen Tekeste, Hani Saleh, Baker Mohammad, Ahsan Khandoker, Mohammed Ismail
2018 J jnl
IEEE Trans. Biomed. Circuits Syst.
Temesghen Tekeste, Hani Saleh, Baker Mohammad, Ahsan Khandoker, Herbert F. Jelinek, Mohammed Ismail
2018 C conf
ISCAS
Dima Kilani, Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mohammed Ismail
2017 conf
ICECS
Huda Goian, Aamna Alali, Temesghen Habte, Hani Saleh
2017 C conf
VLSI-SoC
Yonatan Kifle, Hani Saleh, Baker Mohammad, Mohammed Ismail
2017 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mohammed Ismail
2017 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mohammed Ismail
2017 conf
ICECS
Ahood Al Jneibi, Menatalla Abououf, Hani Saleh, Lilas Alrahis, Tasneem Assaf, Thanos Stouraitis
2017 conf
ICECS
Bilal Taha, Lilas Alrahis, Tasneem Assaf, Hani Saleh, Naoufel Werghi, Thanos Stouraitis
2017 conf
ICECS
Hamza Al Maharmeh, Hani Saleh, Baker Mohammad, Mohammad Ismail, Thanos Stouraitis
2017 conf
ICECS
Ayesha AlHosani, Sara AlShizawi, Shayma AlAli, Hani Saleh, Tasneem Assaf, Thanos Stouraitis
2017 conf
ICECS
Hadeel Aboueidah, Nasma Abbas, Nadeen El Nachar, Aya Al-Yousef, Mohammad Alhawari, Baker Mohammad, Hani Saleh, Tasneem Assaf, Mohammed Ismail
2017 conf
ICECS
Nourhan Elsayed, Hani Saleh, Baker Mohammad, Mohammed Ismail
2017 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Muhammad Yasin, Temesghen Tekeste, Hani Saleh, Baker Mohammad, Ozgur Sinanoglu, Mohammed Ismail
2016 conf
MWSCAS
Hamad Marzouqi, Mahmoud Al-Qutayri, Khaled Salah, Hani Saleh
2016 C conf
ISCAS
Temesghen Tekeste, Hani Saleh, Baker Mohammad, Ahsan H. Khandoker, Mohammed Ismail
2016 conf
MWSCAS
Abdulqader Nael Mahmoud, Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mohammed Ismail
2016 conf
MWSCAS
Andrzej Sluzek, Hani Saleh
2016 conf
MWSCAS
Dima Kilani, Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mohammed Ismail
2016 J jnl
Microelectron. J.
Maisam Wahbah, Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mohammed Ismail
2016 J jnl
IEEE Trans. Circuits Syst. I Regul. Pap.
Dima Kilani, Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mohammed Ismail
2016 C conf
ISCAS
Mohammad Alhawari, Dima Kilani, Baker Mohammad, Hani Saleh, Mohammed Ismail
2016 conf
MWSCAS
Lilas Al Rahis, Baker Mohammad, Hani Saleh, Mohammad Ismail
2016 conf
MWSCAS
Temesghen Tekeste, Hani Saleh, Baker Mohammad, Mohammed Ismail
2016 conf
MWSCAS
Saif Al Ateeqi Al Junaibi, Nicholas Hallfors, Yarjan Abdul Samad, Hani Saleh, K. Liao, A. F. Isakovic, Mohammed Ismail
2016 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Nourhan Bayasi, Temesghen Tekeste, Hani Saleh, Baker Mohammad, Ahsan H. Khandoker, Mohammed Ismail
2016 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Yasmin Halawani, Baker Mohammad, Dirar Homouz, Mahmoud Al-Qutayri, Hani Saleh
2016 conf
MWSCAS
Muna Darweesh, Temesghen Habte, Hani Saleh, Baker Mohammad, Mohammed Ismail
2016 conf
MWSCAS
Mohammad Alhawari, Temesghen Tekeste, Baker Mohammad, Hani Saleh, Mohammed Ismail
2015 C conf
ISCAS
Nourhan Bayasi, Temesghen Tekeste, Hani Saleh, Baker Mohammad, Mohammed Ismail
2015 C conf
IECON
Sohailah Alyammahi, Ehab Salahat, Hani Saleh, Andrzej Sluzek
2015 C conf
IECON
Ehab Salahat, Hani Saleh, Andrzej Sluzek, Mahmoud Al-Qutayri, Baker Mohammad, Mohammad Ismail
2015 conf
ICCSPA
Ehab Salahat, Hani Saleh, M. Sami Zitouni, Andrzej S. Sluzek, Baker Mohammad, Mahmoud Al-Qutayri, Mohammad Ismail
2015 C conf
ISCAS
Temesghen Tekeste, Nourhan Bayasi, Hani Saleh, Ahsan Khandoker, Baker Mohammad, Mahmoud Al-Qutayri, Mohammed Ismail
2015 conf
ECCTD
Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mohammed Ismail
2015 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Baker S. Mohammad, Hani Saleh, Mohammed Ismail
2015 conf
VTC Fall
Ehab Salahat, Hani Saleh, Andrzej Sluzek, Mahmoud Al-Qutayri, Baker Mohammad, Mohammed Ismail
2015 C conf
ISCAS
Yasmin Halawani, Baker Mohammad, Mahmoud Al-Qutayri, Hani Saleh
2015 C conf
IGARSS
Ehab Salahat, Hani Saleh, Andrzej S. Sluzek, Baker Mohammad, Mahmoud Al-Qutayri, Mohammad Ismail
2015 conf
VTC Spring
Ehab Salahat, Hani Saleh
2015 C conf
IECON
Ehab Salahat, Hani Saleh, Andrzej Sluzek, Mahmoud Al-Qutayri, Baker Mohammad, Mohammad Ismail
2014 conf
ICECS
Ehab Salahat, Mahmoud Al-Qutayri, Saleh R. Al-Araji, Hani Saleh
2014 conf
EMBC
Nourhan Bayasi, Temesghen Tekeste, Hani Saleh, Ahsan Khandoker, Baker Mohammad, Mohammed Ismail
2014 J jnl
IEEE J. Emerg. Sel. Topics Circuits Syst.
Maisam Wahbah, Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mohammed Ismail
2014 conf
ICECS
Dima Kilani, Baker Mohammad, Hani Saleh, Mohammed Ismail
2014 conf
ICECS
Maisam Wahbah, Baker Mohammad, Hani Saleh, Mohammed Ismail
2014 conf
ICECS
Dima Kilani, Baker Mohammad, Hani Saleh, Mohammed Ismail
2014 conf
GlobalSIP
Ehab Salahat, Hani Saleh
2014 conf
ICECS
Dima Kilani, Baker Mohammad, Hani Saleh, Mohammed Ismail
2013 conf
ICECS
Mohammad Alhawari, Baker Mohammad, Hani Saleh, Mohammed Ismail
2013 conf
ICECS
Ehab Salahat, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri, Andrzej Sluzek, Mohammed Ismail
2013 conf
ICECS
Yasmin Halawani, Baker Mohammad, Mahmoud Al-Qutayri, Hani Saleh
2013 conf
ICECS
Yasmin Halawani, Baker Mohammad, Dirar Homouz, Mahmoud Al-Qutayri, Hani Saleh
2013 conf
DTIS
Baker Mohammad, Hani Saleh
2013 conf
DTIS
Mohammad Alhawari, Ahsan Khandoker, Baker Mohammad, Hani Saleh, Kinda Khalaf, Mahmoud Al-Qutayri, Murat Kaya Yapici, Shakti Singh, Mohammed Ismail
2013 conf
IDT
Yasmin Halawani, Baker Mohammad, Dirar Humouz, Mahmoud Al-Qutayri, Hani Saleh
2013 conf
ICECS
Yasmin Halawani, Baker Mohammad, Mahmoud Al-Qutayri, Hani Saleh
2013 conf
ICECS
Temesghen Tekeste, Hani Saleh, Baker Mohammad, Mahmoud Al-Qutayri, Mohammed Ismail
2013 conf
ICECS
Nourhan Bayasi, Hani Saleh, Baker Mohammad, Mohammed Ismail
2011 conf
Intelligent Robots and Computer Vision: Algorithms and Techniques
Khader Mohammad, Sos S. Agaian, Hani Saleh
2011 conf
Multimedia on Mobile Devices / Multimedia Content Access: Algorithms and Systems
Khader Mohammad, Sos S. Agaian, Hani Saleh
2011 conf
Multimedia on Mobile Devices / Multimedia Content Access: Algorithms and Systems
Khader Mohammad, Sos S. Agaian, Hani Saleh
2009 B conf
SMC
Hani Saleh, Sos S. Agaian, Khader Mohammad
2008 C conf
ICCD
Adnan Suleiman, Hani Saleh, Adel Hussein, David Akopian
2007 C conf
ICCD
Hani Saleh, Bassam Jamil Mohd, Adnan Aziz, Earl E. Swartzlander Jr.
redb/extractors/decompiler/DecompileBinja.py
← Index redb/extractors/decompiler/DecompileBinja.py python
import hashlib
import inspect
import json
import logging
import os
import signal
import time
from datetime import datetime, timezone
from typing import Dict, Any, Optional
from pathlib import Path
import subprocess
import sys

from redb.extractors.enum import Tag
from redb.extractors.extractor import Extractor
import magic
import pefile
from elftools.elf.elffile import ELFFile

# Import our BinjaDecompiler (conditional)
from redb.extractors.decompiler.bninja.decompiler import BinaryNinjaDecompiler

class DecompileBinja(Extractor):
    def __init__(
        self,
        filepath,
        log,
        exporters=None,
        index_prefix=None,
        elastic_index=None,
        known_benign=False,
        known_malicious=False,
        filetype=None,
        decompile_modules=None,
    ):
        super().__init__(
            filepath,
            log,
            exporters,
            index_prefix,
            elastic_index,
            known_benign,
            known_malicious,
        )
        self.log.debug(inspect.currentframe().f_code.co_name)

        # Check if Binary Ninja is available
       # if not BINARYNINJA_AVAILABLE:
        #     self.log.error("Binary Ninja is not available in this container")
        #    raise ImportError(
        #        "Binary Ninja module not found - not available in feature extraction container"
        #    )
        self.analysis_results = None
        self.binja_decompiler = None
        self.filetype = filetype
        self.decompile_modules = decompile_modules or {"all"}
        self.goresym_data = None
        self.goresym_output_path = None

        # Convert TIMEOUT to integer with a default of 1200 seconds (20 minutes)
        try:
            self.BINJA_TIMEOUT = int(os.getenv("BINJA_TIMEOUT", "1200"))
        except ValueError:
            self.log.warning(
                "Invalid BINJA_TIMEOUT value, using default of 1200 seconds"
            )
            self.BINJA_TIMEOUT = 1200

        # Convert TIMEOUT to integer with a default of 1200 seconds (20 minutes)
        try:
            self.DECOMPILE_EXTRACTOR_TIMEOUT = int(
                os.getenv("DECOMPILE_EXTRACTOR_TIMEOUT", "2580")
            )
        except ValueError:
            self.log.warning(
                "Invalid DECOMPILE_EXTRACTOR_TIMEOUT value, using default of 2580 seconds"
            )
            self.DECOMPILE_EXTRACTOR_TIMEOUT = 2580

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.cleanup_run()

    def calculate_md5(self, input_str):
        """Calculate MD5 hash of a string."""
        return hashlib.md5(input_str.encode("utf-8")).hexdigest()

    def is_dotnet(self):
        """Check if the binary is a .NET assembly.

        Returns:
            bool: True if the file is a .NET assembly, False otherwise
        """
        try:
            if self.filetype == "pebin":
                file_type = magic.from_buffer(self.binary)
                if ".Net" in file_type:
                    return True
                pe = pefile.PE(self.filepath)
                for entry in pe.OPTIONAL_HEADER.DATA_DIRECTORY:
                    # IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR is typically 14
                    if (
                        entry.name == "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR"
                        and entry.Size > 0
                    ):
                        return True
                return False
            return False
        except AttributeError as e:
            self.log.error(
                f"AttributeError error dotnet file {self.hash.sha256} Full error : {e}"
            )
            return False

    def is_golang(self):
        """Check if the binary is a Go-compiled binary (heuristic).

        Supports PE and ELF binaries.
        """
        try:
            if self.filetype == "pebin":
                pe = pefile.PE(self.filepath)
                signatures = [b"Go build ID:", b"runtime.main", b"main.main"]

                for section in pe.sections:
                    data = section.get_data()
                    if any(sig in data for sig in signatures):
                        return True

                return False

            elif self.filetype == "elf":
                with open(self.filepath, "rb") as f:
                    elf = ELFFile(f)

                    # 1. Section-based checks
                    section_names = [sec.name for sec in elf.iter_sections()]
                    if any(
                        s in section_names
                        for s in (".note.go.buildid", ".gopclntab")
                    ):
                        return True

                    # 2. String scan in loadable sections
                    signatures = [
                        b"Go build ID:",
                        b"runtime.main",
                        b"runtime.goexit",
                        b"runtime.morestack",
                        b"main.main",
                    ]

                    for sec in elf.iter_sections():
                        if sec["sh_flags"] & 0x2:  # SHF_ALLOC
                            data = sec.data()
                            if any(sig in data for sig in signatures):
                                return True

                return False

            return False

        except Exception as e:
            self.log.error(
                f"Golang detection error {self.hash.sha256}: {e}"
            )
            return False

    def cleanup_run(self):
        """Clean up after analysis."""
        try:
            # BinaryNinjaDecompiler uses context manager pattern (__enter__/__exit__)
            # Cleanup happens automatically when exiting the 'with' block
            self.binja_decompiler = None

            # Clean up goresym temp file if it exists (keep in debug mode)
            if self.goresym_output_path and os.path.exists(self.goresym_output_path):
                if self.log.isEnabledFor(logging.DEBUG):
                    self.log.debug(f"Debug mode: keeping goresym output at {self.goresym_output_path}")
                else:
                    os.remove(self.goresym_output_path)
                    self.goresym_output_path = None

            # Force garbage collection
            import gc

            gc.collect()

        except Exception as e:
            self.log.error(f"Error in cleanup: {e}")

    def run_goresym(self, binary_path, output_json_path):
        """
            Run goresym on a Go binary and export its JSON output to a file.
            binary_path: path to the Go binary to analyze
            output_json_path: path where the JSON output will be saved
            """
        binary_path = str(Path(binary_path).resolve())
        output_json_path = str(Path(output_json_path).resolve())
        goresym_path = os.getenv("GORESYM_PATH", "GoReSym")

        try:
            # Example: goresym -t json /path/to/binary
            self.log.info("DEBUG: starting GoReSym")
            result = subprocess.run(
                [goresym_path, binary_path],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
            )
        except FileNotFoundError:
            self.log.error("Error: 'goresym' not found in PATH. Make sure it is installed.")
            raise
        except subprocess.CalledProcessError as e:
            self.log.error("Error during goresym execution:")
            self.log.error(e.stderr)


        # Assuming goresym emits valid JSON to stdout.
        try:
            parsed = json.loads(result.stdout)
            # Store parsed JSON for later export to ClickHouse
            self.goresym_data = parsed
        except json.JSONDecodeError:
            # If it's not valid JSON, save the raw output instead.
            self.log.error("Warning: goresym output is not valid JSON; saving raw.")
            with open(output_json_path, "w", encoding="utf-8") as f:
                f.write(result.stdout)
            return

        # Save pretty-printed JSON for readability and debugging (used by BinaryNinja)
        with open(output_json_path, "w", encoding="utf-8") as f:
            json.dump(parsed, f, ensure_ascii=False, indent=2)
        self.goresym_output_path = output_json_path

        self.log.debug(f"goresym output saved to: {output_json_path}")

    def analyze_binary(self) -> Optional[Dict[str, Any]]:
        """Run Binary Ninja analysis and return results."""
        self.log.debug("Starting binary analysis")
        # if the binary is dotnet (only PE)
        if self.is_dotnet():
            self.log.debug("Skipping .NET binary - decompilation not supported")
            return None

        output_json_path = None
        ## if golang: run goresym
        try:
            if self.is_golang():
                output_json_path = "./goResym.json"
                self.run_goresym(self.filepath, output_json_path)
        except Exception as e:
            self.log.error(f"Error on GoReSym extraction: {e}")

        try:
            # Use BinaryNinjaDecompiler as a context manager to ensure proper setup/cleanup
            with BinaryNinjaDecompiler(
                filepath=self.filepath,
                timeout=self.BINJA_TIMEOUT,
                log=self.log,
                exporters=self.exporters,
                index_prefix=self.index_prefix,
                filetype=self.filetype,
                goresym=output_json_path,
                decompile_modules=self.decompile_modules,
            ) as decompiler:
                self.binja_decompiler = decompiler

                if decompiler.extract():
                    # Store results before context manager exits
                    results = decompiler.analysis_results
                    return results
                else:
                    self.log.error("BinaryNinjaDecompiler extraction failed")
                    return None

        except Exception as e:
            self.log.error(f"Error in Binary Ninja analysis: {e}")
            import traceback
            self.log.error(f"Traceback: {traceback.format_exc()}")
            return None

        finally:
            self.cleanup_run()

    def extract(self):
        """Extract and process all analysis results."""
        self.log.debug(inspect.currentframe().f_code.co_name)

        # Create a flag to track if extraction completed
        extraction_completed = False
        extraction_result = False
        extraction_error = None

        # Define the extraction process as a separate function
        def do_extraction():
            nonlocal extraction_completed, extraction_result, extraction_error
            try:
                results = self.analyze_binary()
                if not results:
                    extraction_result = False
                else:
                    self.analysis_results = results
                    # Add file hashes from parent Extractor class to analysis results
                    self.analysis_results["sha256"] = self.sha256
                    self.analysis_results["sha1"] = self.sha1
                    self.analysis_results["md5"] = self.md5
                    extraction_result = True
            except Exception as e:
                extraction_error = e
                extraction_result = False
            finally:
                extraction_completed = True

        # Run extraction directly with signal-based timeout (no thread overhead).
        # SIGALRM is delivered by the OS, so there's no GIL contention or polling.
        old_handler = signal.getsignal(signal.SIGALRM)
        def _timeout_handler(signum, frame):
            raise TimeoutError("Extraction timed out")

        signal.signal(signal.SIGALRM, _timeout_handler)
        signal.alarm(self.DECOMPILE_EXTRACTOR_TIMEOUT)
        try:
            do_extraction()
        except TimeoutError:
            self.log.error(
                f"Extraction timed out after {self.DECOMPILE_EXTRACTOR_TIMEOUT} seconds"
            )
            self.cleanup_run()
            return None
        finally:
            signal.alarm(0)
            signal.signal(signal.SIGALRM, old_handler)

        if extraction_error:
            self.log.error(f"Error in extraction: {extraction_error}")
            return None

        # Return the actual analysis results, not just a boolean
        return self.analysis_results if extraction_result else None

    def prepare_export_data(self, exporter_type: str) -> Any:
        """Prepare data for database export."""
        self.log.debug(inspect.currentframe().f_code.co_name)
        if not self.analysis_results:
            return None

        # # Delegate to the BinjaDecompiler for consistent export formatting
        # if self.binja_decompiler:
        #     return self.binja_decompiler.prepare_export_data(exporter_type)
        # else:
        #     self.log.error("BinjaDecompiler not available for export preparation")
        #     return None

        if exporter_type == "ClickHouseExporter":
            now = datetime.now(timezone.utc)

            def prepare_array_field(value, array_type):
                """Helper to prepare array fields with proper null handling"""
                if value is None:
                    return []
                return value

            # Add a helper function to handle empty strings
            def ensure_not_empty(value, default="UNKNOWN"):
                """Ensure a string value is not empty"""
                if value is None or value == "":
                    return default
                return value

            def prepare_register_usage_map(register_dict):
                """Convert register usage dict to Map format with tuples
                Input: {"rbx": {"reads": 3, "writes": 1}, ...}
                Output: {"rbx": (3, 1), ...}
                """
                if not register_dict:
                    return {}
                return {
                    reg: (info.get("reads", 0), info.get("writes", 0))
                    for reg, info in register_dict.items()
                }


            decompile_modules = getattr(self, "decompile_modules", {"all"})
            run_all = "all" in decompile_modules
            run_decompilation = run_all or "decompilation" in decompile_modules
            run_disassembly = run_all or "disassembly" in decompile_modules
            run_llil = run_all or "llil" in decompile_modules
            run_cfg = run_all or "cfg" in decompile_modules
            run_strings = run_all or "strings" in decompile_modules

            export = {"multi_table": True}

            # Decompilation tables
            if run_decompilation:
                export["decompiled_content"] = {
                    "table": "code_binja_decompiled_functions_content",
                    "data": [
                        [
                            f["decompiled_function_hash"],
                            f["decompiled_function"],
                            f["function_type"],
                            f.get("flattened_score"),
                            f.get("mba_score"),
                            now,
                        ]
                        for f in self.analysis_results["decompiled"]
                    ],
                    "column_names": [
                        "decompiled_function_hash",
                        "decompiled_function",
                        "function_type",
                        "flattened_score",
                        "mba_score",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'THUNK'=3, 'EXTERNAL'=4, 'UNKNOWN'=5)",
                        "Nullable(Float64)",
                        "Nullable(Float64)",
                        "DateTime64(3, 'UTC')",
                    ],
                }
                export["decompiled_refs"] = {
                    "table": "code_binja_decompiled_functions_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            self.analysis_results["sha1"],
                            self.analysis_results["md5"],
                            f["decompiled_function_hash"],
                            f.get("disassembled_function_hash"),
                            f["decompiled_function_name"],
                            f["decompiled_function_prototype"],
                            f["decompiled_function_address"],
                            prepare_array_field(f.get("functions_caller"), "Array(String)"),
                            prepare_array_field(f.get("functions_call"), "Array(String)"),
                            now,
                        ]
                        for f in self.analysis_results["decompiled"]
                    ],
                    "column_names": [
                        "sha256",
                        "sha1",
                        "md5",
                        "decompiled_function_hash",
                        "disassembled_function_hash",
                        "decompiled_function_name",
                        "decompiled_function_prototype",
                        "decompiled_function_address",
                        "functions_caller",
                        "functions_call",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(40)",
                        "FixedString(32)",
                        "FixedString(64)",
                        "Nullable(FixedString(64))",
                        "LowCardinality(String)",
                        "LowCardinality(String)",
                        "UInt64",
                        "Array(String)",
                        "Array(String)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Disassembly tables
            if run_disassembly:
                export["disassembled_content"] = {
                    "table": "code_binja_disassembled_functions_content",
                    "data": [
                        [
                            f["disassembled_function_hash"],
                            f.get("disassembled_function", ""),
                            f.get("disassembled_function_no_addresses", ""),
                            f.get("function_type", "UNKNOWN"),
                            f.get("instructions_count", 0),
                            prepare_array_field(
                                f.get("instructions_types"), "LowCardinality(String)"
                            ),
                            f.get("control_flow_count", 0),
                            prepare_array_field(
                                f.get("memory_access_pattern"), "LowCardinality(String)"
                            ),
                            prepare_array_field(
                                f.get("register_usage"), "LowCardinality(String)"
                            ),
                            f.get("data_references_count", 0),
                            f.get("max_block_size"),
                            f.get("num_calls"),
                            f.get("stack_size"),
                            now,
                        ]
                        for f in self.analysis_results["disassembled"]
                    ],
                    "column_names": [
                        "disassembled_function_hash",
                        "disassembled_function",
                        "disassembled_function_no_addresses",
                        "function_type",
                        "instructions_count",
                        "instructions_types",
                        "control_flow_count",
                        "memory_access_pattern",
                        "register_usage",
                        "data_references_count",
                        "max_block_size",
                        "num_calls",
                        "stack_size",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "String",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'THUNK'=3, 'EXTERNAL'=4, 'UNKNOWN'=5)",
                        "UInt32",
                        "Array(LowCardinality(String))",
                        "UInt32",
                        "Array(LowCardinality(String))",
                        "Array(LowCardinality(String))",
                        "UInt32",
                        "Nullable(UInt32)",
                        "Nullable(UInt32)",
                        "Nullable(Int32)",
                        "DateTime64(3, 'UTC')",
                    ],
                }
                export["disassembled_refs"] = {
                    "table": "code_binja_disassembled_functions_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            self.analysis_results["sha1"],
                            self.analysis_results["md5"],
                            f["disassembled_function_hash"],
                            f.get("decompiled_function_hash"),
                            f["disassembled_function_name"],
                            f["disassembled_function_address"],
                            f.get("tlsh_disassembly"),
                            f.get("tlsh_llil"),
                            now,
                        ]
                        for f in self.analysis_results["disassembled"]
                    ],
                    "column_names": [
                        "sha256",
                        "sha1",
                        "md5",
                        "disassembled_function_hash",
                        "decompiled_function_hash",
                        "disassembled_function_name",
                        "disassembled_function_address",
                        "tlsh_disassembly",
                        "tlsh_llil",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(40)",
                        "FixedString(32)",
                        "FixedString(64)",
                        "Nullable(FixedString(64))",
                        "LowCardinality(String)",
                        "UInt64",
                        "Nullable(FixedString(72))",
                        "Nullable(FixedString(72))",
                        "DateTime64(3, 'UTC')",
                    ],
                }
                # Function similarity metrics table (derived from disassembly data)
                # Lookup maps to join LLIL/MLIL features by disassembled_function_hash
                llil_by_hash = {
                    l.get("disassembled_function_hash"): l
                    for l in self.analysis_results.get("llil", [])
                    if l and l.get("disassembled_function_hash")
                }
                mlil_by_hash = {
                    m.get("disassembled_function_hash"): m
                    for m in self.analysis_results.get("mlil", [])
                    if m and m.get("disassembled_function_hash")
                }

                export["function_similarity_metrics"] = {
                    "table": "code_binja_function_similarity_metrics",
                    "data": [
                        [
                            f["disassembled_function_hash"],
                            f.get("cyclomatic_complexity"),
                            f.get("tlsh_disassembly"),
                            f.get("tlsh_llil"),
                            prepare_array_field(f.get("minhash"), "Array(UInt8)"),
                            (llil_by_hash.get(f["disassembled_function_hash"]) or {}).get("tlsh_llil"),
                            (llil_by_hash.get(f["disassembled_function_hash"]) or {}).get(
                                "tlsh_instruction_typed_llil"),
                            prepare_array_field(
                                (llil_by_hash.get(f["disassembled_function_hash"]) or {}).get("minhash_llil_skeleton"),
                                "Array(UInt8)",
                            ),
                            prepare_array_field(
                                (llil_by_hash.get(f["disassembled_function_hash"]) or {}).get("minhash_llil_typed"),
                                "Array(UInt8)",
                            ),
                            (mlil_by_hash.get(f["disassembled_function_hash"]) or {}).get("tlsh_mlil_skeleton"),
                            (mlil_by_hash.get(f["disassembled_function_hash"]) or {}).get("tlsh_mlil_typed"),
                            prepare_array_field(
                                (mlil_by_hash.get(f["disassembled_function_hash"]) or {}).get("minhash_mlil_skeleton"),
                                "Array(UInt8)",
                            ),
                            prepare_array_field(
                                (mlil_by_hash.get(f["disassembled_function_hash"]) or {}).get("minhash_mlil_typed"),
                                "Array(UInt8)",
                            ),
                            now,
                        ]
                        for f in self.analysis_results.get("disassembled", [])
                    ],
                    "column_names": [
                        "disassembled_function_hash",
                        "cyclomatic_complexity",
                        "tlsh_disassembly",
                        "tlsh_llil",
                        "minhash",
                        "tlsh_llil_new",
                        "tlsh_instruction_typed_llil",
                        "minhash_llil_skeleton",
                        "minhash_llil_typed",
                        "tlsh_mlil_skeleton",
                        "tlsh_mlil_typed",
                        "minhash_mlil_skeleton",
                        "minhash_mlil_typed",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "Nullable(UInt16)",
                        "Nullable(FixedString(72))",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        # new
                        "Nullable(FixedString(72))",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        "Array(UInt8)",
                        "Nullable(FixedString(72))",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        "Array(UInt8)",
                        "DateTime64(3, 'UTC')",
                    ],
                }


            # LLIL tables
            if run_llil:
                export["llil_content"] = {
                    "table": "code_binja_llil_functions_content",
                    "data": [
                        [
                            f["sha256_llil"],
                            f["function_type"],
                            prepare_array_field(
                                f.get("instructions_types_llil"), "LowCardinality(String)"
                            ),
                            f.get("control_flow_count_llil", 0),
                            prepare_array_field(
                                f.get("memory_access_pattern_llil"), "LowCardinality(String)"
                            ),
                            prepare_register_usage_map(f.get("register_usage", {})),
                            f.get("total_reg_reads", 0),
                            f.get("total_reg_written", 0),
                            f.get("data_references_count", 0),
                            f.get("max_block_size"),
                            f.get("num_calls"),
                            f.get("stack_size"),
                            prepare_array_field(f.get("body_llil_vector"), "Array(Tuple(UInt32, Array(UInt16)))"),
                            now,
                        ]
                        for f in self.analysis_results.get("llil", [])
                    ],
                    "column_names": [
                        "llil_function_hash",
                        "function_type",
                        "instructions_types_llil",
                        "control_flow_count_llil",
                        "memory_access_pattern_llil",
                        "register_usage_llil",
                        "total_reg_reads",
                        "total_reg_written",
                        "data_references_count",
                        "max_block_size",
                        "num_calls",
                        "stack_size",
                        "body_llil_vector",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'THUNK'=3, 'EXTERNAL'=4, 'UNKNOWN'=5)",
                        "Array(LowCardinality(String))",
                        "UInt32",
                        "Array(LowCardinality(String))",
                        "Map(LowCardinality(String), Tuple(UInt32, UInt32))",
                        "UInt32",
                        "UInt32",
                        "UInt32",
                        "Nullable(UInt32)",
                        "Nullable(UInt32)",
                        "Nullable(Int32)",
                        "Array(Tuple(UInt32, Array(UInt16)))",
                        "DateTime64(3, 'UTC')",
                    ],
                }
                export["llil_refs"] = {
                    "table": "code_binja_llil_functions_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            self.analysis_results["sha1"],
                            self.analysis_results["md5"],
                            f.get("sha256_llil"),
                            f.get("disassembled_function_hash"),
                            f.get("function_address"),
                            f.get("tlsh_disassembly"),
                            f.get("tlsh_llil"),
                            now,
                        ]
                        for f in self.analysis_results.get("llil", [])
                    ],
                    "column_names": [
                        "sha256",
                        "sha1",
                        "md5",
                        "llil_function_hash",
                        "disassembled_function_hash",
                        "function_address",
                        "tlsh_disassembly",
                        "tlsh_llil",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(40)",
                        "FixedString(32)",
                        "Nullable(FixedString(64))",
                        "FixedString(64)",
                        "UInt64",
                        "Nullable(FixedString(72))",
                        "Nullable(FixedString(72))",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Errors table (always include if per-function loop ran)
            if run_decompilation or run_disassembly or run_llil or run_cfg:
                export["function_analysis_errors"] = {
                    "table": "new_function_analysis_errors_binja",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f["function_name"],
                            f["function_address"],
                            f.get("error_location", "unknown"),
                            f.get("error_message", ""),
                            f.get("error_details", ""),
                            f.get("error_type", "unknown"),
                            self.calculate_md5(
                                f"{f.get('error_message', '')}{f['function_name']}{f['function_address']}{f.get('error_location', 'unknown')}"
                            ),
                            "new",
                            now,
                        ]
                        for f in self.analysis_results.get("errors", [])
                    ],
                    "column_names": [
                        "sha256",
                        "function_name",
                        "function_address",
                        "error_location",
                        "error_message",
                        "error_details",
                        "error_type",
                        "error_hash",
                        "status",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "Nullable(String)",
                        "UInt64",
                        "LowCardinality(String)",
                        "Nullable(String)",
                        "Nullable(String)",
                        "Nullable(String)",
                        "FixedString(32)",
                        "Enum8('new'=1, 'investigating'=2, 'fixed'=3, 'wontfix'=4)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Strings table
            if run_strings:
                export["strings_raw"] = {
                    "table": "code_binja_strings_raw",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            s["string"],
                            s["string_raw"],
                            s["string_encoding"],
                            s["string_offset"],
                            s["string_length"],
                            s["string_raw_length"],
                            s["string_entropy"],
                        ]
                        for s in self.analysis_results.get("strings", [])
                    ],
                    "column_names": [
                        "sha256",
                        "string",
                        "string_raw",
                        "string_encoding",
                        "string_offset",
                        "string_length",
                        "string_raw_length",
                        "string_entropy",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "String",
                        "LowCardinality(String)",
                        "UInt64",
                        "UInt32",
                        "UInt32",
                        "Float32",
                    ],
                }

            # CFG function-level features table
            if run_cfg:
                export["cfg_functions"] = {
                    "table": "code_binja_cfg_functions",
                    "data": [
                        [
                            cfg.get("disassembled_function_hash"),
                            cfg["cfg_topology_hash"],
                            cfg["block_count"],
                            cfg["edge_count"],
                            cfg.get("llil_total_operations", 0),
                            cfg.get("call_count", 0),
                            cfg["cyclomatic_complexity"],
                            cfg.get("loop_count", 0),
                            cfg.get("max_depth", 0),
                            cfg.get("max_fan_out", 0),
                            cfg.get("md_index_topdown", 0),
                            cfg.get("md_index_bottomup", 0),
                            cfg.get("prime_product_llil", 0),
                            cfg.get("cfg_feature_tlsh"),
                            cfg.get("wl_minhash", []),
                            cfg.get("bb_features", []),
                            cfg.get("cfg_adjacency", []),
                            now,
                        ]
                        for cfg in self.analysis_results.get("cfg", [])
                        if cfg is not None
                    ],
                    "column_names": [
                        "disassembled_function_hash",
                        "cfg_topology_hash",
                        "block_count",
                        "edge_count",
                        "llil_total_operations",
                        "call_count",
                        "cyclomatic_complexity",
                        "loop_count",
                        "max_depth",
                        "max_fan_out",
                        "md_index_topdown",
                        "md_index_bottomup",
                        "prime_product_llil",
                        "cfg_feature_tlsh",
                        "wl_minhash",
                        "bb_features",
                        "cfg_adjacency",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(16)",
                        "UInt16",
                        "UInt16",
                        "UInt32",
                        "UInt16",
                        "UInt16",
                        "UInt8",
                        "UInt16",
                        "UInt8",
                        "UInt64",
                        "UInt64",
                        "UInt64",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        "Array(Array(UInt16))",
                        "Array(UInt32)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # GoReSym metadata table (only if goresym data exists)
            if self.goresym_data:
                export["golang_metadata"] = {
                    "table": "redb_golang_metadata",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            json.dumps(self.goresym_data),
                            now,
                        ]
                    ],
                    "column_names": [
                        "sha256",
                        "goresym",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "JSON",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            return export

    def tag(self) -> str:
        """Return the tag for this extractor."""
        return Tag.DECOMPILED.value

    def get_clickhouse_table(self) -> str:
        """Not used directly as we're handling multiple tables."""
        pass


if __name__ == "__main__":
    # Setup basic logging
    import logging
    import time

    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger("DecompileBinja")

    # Parse command line arguments
    import argparse

    parser = argparse.ArgumentParser(description="Binary Ninja Decompiler Wrapper")
    parser.add_argument("filepath", help="Path to the binary file to analyze")
    parser.add_argument(
        "--output", "-o", help="Output JSON file path (default: stdout)"
    )
    parser.add_argument(
        "--timeout",
        "-t",
        type=int,
        default=1200,
        help="Analysis timeout in seconds (default: 1200)",
    )
    args = parser.parse_args()
    start = time.perf_counter()
    # Create and run the extractor
    with DecompileBinja(args.filepath, logger) as extractor:
        success = extractor.extract()
        end = time.perf_counter()
        if not success:
            logger.error("Analysis failed")
            exit(1)

        # Output results
        if args.output:
            with open(args.output, "w") as f:
                json.dump(extractor.analysis_results, f)
            logger.info(f"Results written to {args.output}")
        else:
            print((extractor.analysis_results))
            with open("diff", "w") as f:
                f.write(str(f"{end - start:.3f} seconds"))