K. G. Subramanian

145 papers B 2C 18Misc 2Journal 71Unranked 46
YearRankTypeTitle / Venue / Authors
2025 conf
Languages of Cooperation and Communication
Rodica Ceterchi, Marian Gheorghe, Lakshmanan Kuppusamy, K. G. Subramanian
2025 J jnl
J. Membr. Comput.
Rodica Ceterchi, Marian Gheorghe, Lakshmanan Kuppusamy, K. G. Subramanian
2024 J jnl
J. Autom. Lang. Comb.
Somnath Bera, Atulya K. Nagar, K. G. Subramanian
2024 J jnl
J. Membr. Comput.
Somnath Bera, Atulya K. Nagar, K. G. Subramanian, Gexiang Zhang
2023 J jnl
Theor. Comput. Sci.
Somnath Bera, Atulya K. Nagar, Sastha Sriram, K. G. Subramanian
2022 J jnl
J. Membr. Comput.
Somnath Bera, Rodica Ceterchi, Sastha Sriram, K. G. Subramanian
2021 J jnl
Theor. Comput. Sci.
Luping Zhang, Fei Xu, Ajeesh Ramanujan, K. G. Subramanian
2021 J jnl
J. Membr. Comput.
Rodica Ceterchi, Luping Zhang, K. G. Subramanian, Gexiang Zhang
2021 C conf
DLT
Nobin Thomas, Lisa Mathew, Somnath Bera, Atulya K. Nagar, K. G. Subramanian
2021 J jnl
Ars Math. Contemp.
Nobin Thomas, Lisa Mathew, Sastha Sriram, K. G. Subramanian
2020 J jnl
Int. J. Found. Comput. Sci.
Zi Jing Chern, K. G. Subramanian, Azhana Ahmad, Wen Chean Teh
2020 conf
Int. Conf. on Membrane Computing
Sastha Sriram, Somnath Bera, K. G. Subramanian
2020 J jnl
J. Membr. Comput.
Rodica Ceterchi, K. G. Subramanian
2020 J jnl
Int. J. Found. Comput. Sci.
Somnath Bera, Rodica Ceterchi, Kalpana Mahalingam, K. G. Subramanian
2019 conf
SocProS (1)
G. Samdanielthompson, N. Gnanamalar David, Atulya K. Nagar, K. G. Subramanian
2019 J jnl
Adv. Appl. Math.
Lisa Mathew, Nobin Thomas, Somnath Bera, K. G. Subramanian
2018 ch.
Reversibility and Universality
K. G. Subramanian, Sastha Sriram, Bosheng Song, Linqiang Pan
2018 conf
Enjoying Natural Computing
Rodica Ceterchi, Atulya K. Nagar, K. G. Subramanian
2018 conf
Int. Conf. on Membrane Computing
Rodica Ceterchi, Atulya K. Nagar, K. G. Subramanian
2018 C conf
IWCIA
A. Dharani, R. Stella Maragatham, Atulya K. Nagar, K. G. Subramanian
2018 C conf
Diagrams
Ibrahim Venkat, Robinson Thamburaj, K. G. Subramanian, Philippe De Wilde
2018 J jnl
Theor. Comput. Sci.
Linqiang Pan, Bosheng Song, Atulya K. Nagar, K. G. Subramanian
2018 J jnl
Theor. Comput. Sci.
Wen Chean Teh, K. G. Subramanian, Somnath Bera
2018 J jnl
Int. J. Found. Comput. Sci.
Somnath Bera, Kalpana Mahalingam, K. G. Subramanian
2017 J jnl
Theor. Comput. Sci.
Artiom Alhazov, Henning Fernau, Rudolf Freund, Sergiu Ivanov, Rani Siromoney, K. G. Subramanian
2017 conf
BIC-TA
Kalpana Mahalingam, Prithwineel Paul, Bosheng Song, Linqiang Pan, K. G. Subramanian
2017 J jnl
Fundam. Informaticae
Henning Fernau, Rudolf Freund, Rani Siromoney, K. G. Subramanian
2017 J jnl
CoRR
Henning Fernau, Markus L. Schmid, K. G. Subramanian
2016 conf
Int. Conf. on Membrane Computing
Pradeep Isawasan, Ravie Chandren Muniyandi, Ibrahim Venkat, K. G. Subramanian
2016 conf
DCFS
Henning Fernau, Rudolf Freund, Rani Siromoney, K. G. Subramanian
2016 J jnl
Int. J. Artif. Intell. Soft Comput.
G. Samdanielthompson, N. Gnanamalar David, K. G. Subramanian
2016 J jnl
Math. Comput. Sci.
Bharati Rajan, Ibrahim Venkat, K. G. Subramanian
2016 conf
ICTCSDM
G. Samdanielthompson, N. Gnanamalar David, K. G. Subramanian
2016 J jnl
ACM Trans. Intell. Syst. Technol.
Azhar Mohd Ibrahim, Ibrahim Venkat, K. G. Subramanian, Ahamad Tajudin Khader, Philippe De Wilde
2016 conf
BIC-TA (1)
Rodica Ceterchi, Linqiang Pan, Bosheng Song, K. G. Subramanian
2016 conf
Int. Conf. on Membrane Computing
Linqiang Pan, Bosheng Song, K. G. Subramanian
2015 conf
IVIC
Pradeep Isawasan, Ibrahim Venkat, Ravie Chandren Muniyandi, K. G. Subramanian
2015 conf
BIC-TA
K. G. Subramanian, Atulya K. Nagar, Linqiang Pan
2015 J jnl
Ann. Math. Artif. Intell.
Henning Fernau, Rudolf Freund, Markus L. Schmid, K. G. Subramanian, Petra Wiederhold
2015 conf
IBICA
K. G. Subramanian, G. Samdanielthompson, N. Gnanamalar David, Atulya K. Nagar
2015 C conf
MCU
Henning Fernau, Rudolf Freund, Rani Siromoney, K. G. Subramanian
2015 C conf
CiE
Rodica Ceterchi, K. G. Subramanian, Ibrahim Venkat
2015 C conf
IWCIA
K. G. Subramanian, M. Geethalakshmi, N. Gnanamalar David, Atulya K. Nagar
2015 J jnl
ACM Comput. Surv.
Bisan Alsalibi, Ibrahim Venkat, K. G. Subramanian, Syaheerah Lebai Lutfi, Philippe De Wilde
2015 J jnl
Fundam. Informaticae
Yunyun Niu, Ibrahim Venkat, Ahamad Tajudin Khader, K. G. Subramanian
2014 C conf
IWCIA
Zbynek Krivka, Carlos Martín-Vide, Alexander Meduna, K. G. Subramanian
2014 J jnl
J. Comput. Sci.
K. G. Subramanian, Pradeep Isawasan, Ibrahim Venkat, Linqiang Pan, Atulya Nagar
2014 conf
Discrete Mathematics and Computer Science
Adrian Atanasiu, Kalpana Mahalingam, K. G. Subramanian
2014 conf
BIC-TA
Yunyun Niu, Ibrahim Venkat, Ahamad Tajudin Khader, K. G. Subramanian
2013 conf
UCNC
Henning Fernau, Rudolf Freund, Sergiu Ivanov, Markus L. Schmid, K. G. Subramanian
2013 C conf
MCU
Maurice Margenstern, K. G. Subramanian
2013 J jnl
Discret. Appl. Math.
K. G. Subramanian, Ibrahim Venkat, Erzsébet Csuhaj-Varjú
2013 C conf
MCU
Rudolf Freund, Sergiu Ivanov, Marion Oswald, K. G. Subramanian
2013 J jnl
Pattern Recognit. Lett.
Ibrahim Venkat, Ahamad Tajudin Khader, K. G. Subramanian, Philippe De Wilde
2013 J jnl
Int. J. Found. Comput. Sci.
K. G. Subramanian, Kalpana Mahalingam, Rosni Abdullah, Atulya K. Nagar
2013 conf
NCMA
Henning Fernau, Markus L. Schmid, K. G. Subramanian
2012 C conf
IWCIA
K. G. Subramanian, Ibrahim Venkat, Petra Wiederhold
2012 J jnl
Int. J. Found. Comput. Sci.
Yunyun Niu, K. G. Subramanian, Ibrahim Venkat, Rosni Abdullah
2012 conf
CCSEIT
K. G. Subramanian, S. Hemalatha, Ibrahim Venkat
2012 J jnl
J. Univers. Comput. Sci.
Yunyun Niu, Jinbang Xu, K. G. Subramanian, Rosni Abdullah
2012 conf
BIC-TA (1)
K. G. Subramanian, Ibrahim Venkat, Linqiang Pan, Atulya K. Nagar
2012 J jnl
Int. J. Found. Comput. Sci.
Kalpana Mahalingam, K. G. Subramanian
2011 C conf
IWCIA
K. G. Subramanian, Kalpana Mahalingam, Rosni Abdullah, Atulya K. Nagar
2011 conf
BIC-TA
K. G. Subramanian, Ibrahim Venkat, Kalpana Mahalingam
2011 conf
IWCIA Special Track on Applications
S. M. Saroja Theerdus Kalavathy, P. Helen Chandra, K. G. Subramanian
2011 conf
CAIP (1)
Ibrahim Venkat, Ahamad Tajudin Khader, K. G. Subramanian, Philippe De Wilde
2011 conf
PAAMS (Special Sessions)
A. Roslin Sagaya Mary, K. G. Subramanian
2011 conf
IWCIA Special Track on Applications
N. Jansirani, V. Rajkumar Dare, K. G. Subramanian
2010 J jnl
Math. Comput. Model.
K. G. Subramanian, Linqiang Pan, See Keong Lee, Atulya K. Nagar
2010 conf
BIC-TA
Yunyun Niu, Jinbang Xu, K. G. Subramanian
2010 conf
BIC-TA
Kalpana Mahalingam, K. G. Subramanian
2010 J jnl
Appl. Math. Lett.
Rosihan M. Ali, B. Adolf Stephen, K. G. Subramanian
2010 conf
CompIMAGE
T. Robinson, S. Jebasingh, Atulya K. Nagar, K. G. Subramanian
2009 conf
UKSim
K. G. Subramanian, M. Geethalakshmi, Atulya K. Nagar, See Keong Lee
2009 J jnl
Fundam. Informaticae
K. G. Subramanian, Rosihan M. Ali, Atulya K. Nagar, Maurice Margenstern
2009 J jnl
Int. J. Found. Comput. Sci.
K. G. Subramanian, Ang Miin Huey, Atulya K. Nagar
2009 J jnl
Discret. Appl. Math.
K. G. Subramanian, Rosihan M. Ali, M. Geethalakshmi, Atulya K. Nagar
2009 conf
Asia International Conference on Modelling and Simulation
K. G. Subramanian, T. Robinson, Atulya K. Nagar
2009 conf
IWCIA Special Track on Applications
K. G. Subramanian, M. Geethalakshmi, Atulya K. Nagar, See Keong Lee
2008 J jnl
Fundam. Informaticae
K. G. Subramanian, Do Long Van, P. Helen Chandra, Nghiem Do Quyen
2008 conf
ISVC (2)
Masilamani Vedhanayagam, Kamala Krithivasan, K. G. Subramanian, Ang Miin Huey
2008 C conf
IWCIA
K. G. Subramanian, Atulya K. Nagar, M. Geethalakshmi
2008 conf
EMS
K. G. Subramanian, M. Geethalakshmi, Atulya K. Nagar, See Keong Lee
2007 conf
Formal Models, Languages and Applications
Adrian Atanasiu, K. G. Subramanian, K. Rangarajan, Patrick S. P. Wang
2007 ed.
Formal Models, Languages and Applications
Madhavan Mukund, K. Rangarajan, K. G. Subramanian
2007 conf
IICAI
K. G. Subramanian, A. Roslin Sagaya Mary, P. Helen Chandra
2007 C conf
MCU
K. G. Subramanian
2006 C conf
IWCIA
K. G. Subramanian, Ramakrishnan Saravanan, P. Helen Chandra
2005 conf
IWINAC (2)
K. S. Dersanambika, K. G. Subramanian, A. Roslin Sagaya Mary
2005 J jnl
Int. J. Pattern Recognit. Artif. Intell.
K. S. Dersanambika, Kamala Krithivasan, Carlos Martín-Vide, K. G. Subramanian
2005 C conf
ICTAC
K. G. Subramanian, A. Roslin Sagaya Mary, K. S. Dersanambika
2004 C conf
IWCIA
K. S. Dersanambika, Kamala Krithivasan, Carlos Martín-Vide, K. G. Subramanian
2004 conf
Aspects of Molecular Computing
Rodica Ceterchi, Carlos Martín-Vide, K. G. Subramanian
2004 J jnl
Int. J. Math. Math. Sci.
V. Ravichandran, Herb Silverman, S. Sivaprasad Kumar, K. G. Subramanian
2004 J jnl
Int. J. Pattern Recognit. Artif. Intell.
P. Helen Chandra, K. G. Subramanian, D. Gnanaraj Thomas
2003 J jnl
Nat. Comput.
Rodica Ceterchi, Madhu Mutyam, Gheorghe Paun, K. G. Subramanian
2003 conf
Workshop on Membrane Computing
K. S. Dersanambika, Kamala Krithivasan, K. G. Subramanian
2003 J jnl
Electron. Notes Discret. Math.
P. Helen Chandra, K. G. Subramanian, D. Gnanaraj Thomas
2003 Misc conf
INDOCRYPT
P. J. Abisha, D. Gnanaraj Thomas, K. G. Subramanian
2003 J jnl
Fundam. Informaticae
Rodica Ceterchi, Radu Gramatovici, Natasa Jonoska, K. G. Subramanian
2002 conf
ICGI
D. Gnanaraj Thomas, M. Humrosia Begam, K. G. Subramanian, S. Gnanasekaran
2002 Misc conf
INDOCRYPT
S. C. Samuel, D. Gnanaraj Thomas, P. J. Abisha, K. G. Subramanian
2001 B conf
DNA
N. Gnanamalar David, K. G. Subramanian, D. Gnanaraj Thomas
2001 C conf
IWCIA
P. Helen Chandra, K. G. Subramanian, D. Gnanaraj Thomas, Do Long Van
2001 J jnl
Inf. Process. Lett.
Ahmad Kadrie, V. Rajkumar Dare, D. Gnanaraj Thomas, K. G. Subramanian
2001 J jnl
J. Autom. Lang. Comb.
K. G. Subramanian, D. Gnanaraj Thomas, P. Helen Chandra, Maia Hoeberechts
2000 conf
ICGI
J. D. Emerald, K. G. Subramanian, D. Gnanaraj Thomas
2000 J jnl
Int. J. Pattern Recognit. Artif. Intell.
V. Rajkumar Dare, K. G. Subramanian, D. Gnanaraj Thomas, Rani Siromoney, B. Le Saec
1999 J jnl
Inf. Process. Lett.
J. D. Emerald, K. G. Subramanian, D. Gnanaraj Thomas
1999 J jnl
Int. J. Pattern Recognit. Artif. Intell.
T. Robinson, K. G. Subramanian, Rani Siromoney, V. Rajkumar Dare
1999 J jnl
Pattern Recognit.
Rani Siromoney, K. G. Subramanian, V. Rajkumar Dare, D. Gnanaraj Thomas
1998 conf
ICGI
J. D. Emerald, K. G. Subramanian, D. Gnanaraj Thomas
1997 C conf
Developments in Language Theory
N. Gnanamalar David, J. D. Emerald, K. G. Subramanian
1996 conf
ICGI
J. D. Emerald, K. G. Subramanian, D. Gnanaraj Thomas
1995 J jnl
Int. J. Pattern Recognit. Artif. Intell.
K. G. Subramanian, Rani Siromoney, V. Rajkumar Dare
1994 J jnl
Inf. Process. Lett.
Rani Siromoney, Lisa Mathew, V. Rajkumar Dare, K. G. Subramanian
1994 J jnl
Int. J. Pattern Recognit. Artif. Intell.
Rani Siromoney, Lisa Mathew, K. G. Subramanian, V. Rajkumar Dare
1993 B conf
ALT
Rani Siromoney, D. Gnanaraj Thomas, K. G. Subramanian, V. Rajkumar Dare
1992 J jnl
Int. J. Pattern Recognit. Artif. Intell.
K. G. Subramanian, Rani Siromoney, V. Rajkumar Dare, Ahmed Saoudi
1992 conf
ICPIA
Rani Siromoney, K. G. Subramanian, V. Rajkumar Dare
1992 J jnl
Int. J. Pattern Recognit. Artif. Intell.
Rani Siromoney, K. G. Subramanian, Lisa Mathew
1992 conf
ICPIA
Rani Siromoney, Lisa Mathew, K. G. Subramanian, V. Rajkumar Dare
1992 J jnl
Theor. Comput. Sci.
K. G. Subramanian, Rani Siromoney, Lisa Mathew
1992 J jnl
Int. J. Pattern Recognit. Artif. Intell.
Rani Siromoney, Abdul Huq, M. Chandrasekaran, K. G. Subramanian
1991 J jnl
Int. J. Pattern Recognit. Artif. Intell.
Maurice Nivat, Ahmed Saoudi, K. G. Subramanian, Rani Siromoney, V. Rajkumar Dare
1990 J jnl
RAIRO Theor. Informatics Appl.
Do Long Van, D. Gnanaraj Thomas, K. G. Subramanian, Rani Siromoney
1989 J jnl
Int. J. Pattern Recognit. Artif. Intell.
Rani Siromoney, K. G. Subramanian, P. J. Abisha
1989 ch.
Array Grammars, Patterns and Recognizers
Rani Siromoney, K. G. Subramanian, P. J. Abisha
1989 ch.
A Perspective in Theoretical Computer Science
Gift Siromoney, Rani Siromoney, K. G. Subramanian, V. Rajkumar Dare, P. J. Abisha
1989 ch.
A Perspective in Theoretical Computer Science
Gift Siromoney, K. G. Subramanian, Rani Siromoney
1989 J jnl
Int. J. Pattern Recognit. Artif. Intell.
K. G. Subramanian, L. Revathi, Rani Siromoney
1989 ch.
Array Grammars, Patterns and Recognizers
K. G. Subramanian, L. Revathi, Rani Siromoney
1987 J jnl
Inf. Process. Lett.
K. G. Subramanian, Rani Siromoney, P. J. Abisha
1987 conf
FSTTCS
K. G. Subramanian, Do Long Van, Rani Siromoney
1985 J jnl
Inf. Sci.
K. G. Subramanian, Rani Siromoney, Gift Siromoney
1985 J jnl
Int. J. Parallel Program.
K. G. Subramanian
1985 J jnl
Bull. EATCS
K. G. Subramanian
1984 J jnl
Theor. Comput. Sci.
Rani Siromoney, K. G. Subramanian, V. Rajkumar Dare
1983 J jnl
Theor. Comput. Sci.
Rani Siromoney, V. Rajkumar Dare, K. G. Subramanian
1982 J jnl
Inf. Sci.
K. G. Subramanian, Rani Siromoney
1982 conf
Graph-Grammars and Their Application to Computer Science
Rani Siromoney, K. G. Subramanian
1982 J jnl
Comput. Graph. Image Process.
Gift Siromoney, Rani Siromoney, K. G. Subramanian
1981 J jnl
Inf. Sci.
Rani Siromoney, K. G. Subramanian
1979 J jnl
Pattern Recognit.
K. G. Subramanian
1976 J jnl
Inf. Control.
Rani Siromoney, K. G. Subramanian, K. Rangarajan
redb/extractors/decompiler/_archive/DecompileBinja-archive.py
← Index redb/extractors/decompiler/_archive/DecompileBinja-archive.py python
import hashlib
import inspect
import json
import os
import time
import threading
from datetime import datetime, timezone
from typing import Dict, Any, Optional

from redb.extractors.enum import Tag
from redb.extractors.extractor import Extractor
import magic
import pefile
import ppdeep
import tlsh

# 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,
    ):
        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

        # 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
        except AttributeError as e:
            self.log.error(
                f"AttributeError error dotnet file {self.hash.sha256} Full error : {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

            # Force garbage collection
            import gc

            gc.collect()

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

    def analyze_binary(self) -> Optional[Dict[str, Any]]:
        """Run Binary Ninja analysis and return results."""
        self.log.debug("Starting binary analysis")

        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,
            ) 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
                    extraction_result = True
            except Exception as e:
                extraction_error = e
                extraction_result = False
            finally:
                extraction_completed = True

        # Start extraction in a separate thread
        extraction_thread = threading.Thread(target=do_extraction)
        extraction_thread.daemon = True
        extraction_thread.start()

        # Wait for the extraction to complete or timeout
        start_time = time.time()
        while (
            not extraction_completed
            and (time.time() - start_time) < self.DECOMPILE_EXTRACTOR_TIMEOUT
        ):
            time.sleep(1)

        if not extraction_completed:
            self.log.error(
                f"Extraction timed out after {self.DECOMPILE_EXTRACTOR_TIMEOUT} seconds"
            )
            # Force cleanup
            self.cleanup_run()
            return None

        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 ssdeep_disassembly(func):
                try:
                    if len(func) > 1:
                        return ppdeep.hash(func)
                    return ""
                except Exception as e:
                    self.log.error(f"Error in disassembly ssdeep hash calculation: {e}")
                    return ""

            def tlsh_disassembly(func):
                try:
                    if len(func) >= 50:
                        return tlsh.hash(func.encode("utf-8"))
                    return ""
                except Exception as e:
                    self.log.error(f"Error in disassembly tlsh hash calculation: {e}")
                    return ""

            return {
                "multi_table": True,
                "decompiled_content": {
                    "table": "code_binja_decompiled_functions_content",
                    "data": [
                        [
                            f["decompiled_function_hash"],
                            f["decompiled_function"],
                            f["function_type"],
                            now,
                        ]
                        for f in self.analysis_results["decompiled"]
                    ],
                    "column_names": [
                        "decompiled_function_hash",
                        "decompiled_function",
                        "function_type",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'THUNK'=3, 'EXTERNAL'=4, 'UNKNOWN'=5)",
                        "DateTime64(3, 'UTC')",
                    ],
                },
                "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["disassembled_function_hash"],  # New linking field
                            f["decompiled_function_name"],
                            f["decompiled_function_prototype"],
                            f["decompiled_function_address"],
                            now,
                        ]
                        for f in self.analysis_results["decompiled"]
                    ],
                    "column_names": [
                        "sha256",
                        "sha1",
                        "md5",
                        "decompiled_function_hash",
                        "disassembled_function_hash",  # New linking field
                        "decompiled_function_name",
                        "decompiled_function_prototype",
                        "decompiled_function_address",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(40)",
                        "FixedString(32)",
                        "FixedString(64)",
                        "Nullable(FixedString(64))",  # New linking field
                        "LowCardinality(String)",
                        "LowCardinality(String)",
                        "UInt64",
                        "DateTime64(3, 'UTC')",
                    ],
                },
                "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", 0),
                            f.get("num_calls", 0),
                            f.get("stack_size", 0),
                            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')",
                    ],
                },
                "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["decompiled_function_hash"],
                            f["disassembled_function_name"],
                            f["disassembled_function_address"],
                            ssdeep_disassembly(
                                f.get("disassembled_function_no_addresses", "")
                            ),
                            tlsh_disassembly(
                                f.get("disassembled_function_no_addresses", "")
                            ),
                            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",
                        "ssdeep_disassembly",
                        "tlsh_disassembly",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(40)",
                        "FixedString(32)",
                        "FixedString(64)",
                        "Nullable(FixedString(64))",
                        "LowCardinality(String)",
                        "UInt64",
                        "Nullable(String)",
                        "Nullable(FixedString(72))",
                        "DateTime64(3, 'UTC')",
                    ],
                },
                "cfg_blocks": {
                    "table": "code_binja_cfg_blocks",
                    "data": [
                        [
                            b["block_id"],
                            self.analysis_results["sha256"],
                            self.analysis_results["sha1"],
                            self.analysis_results["md5"],
                            b["function_address"],
                            b["block_start_address"],
                            b["block_end_address"],
                            b["block_size"],
                            b["instructions_count"],
                            b["block_instructions"],  # MD5 hash of instructions
                            b["predecessor_blocks"],
                            b["successor_blocks"],
                            b["depth"],
                            b["position"],
                            b["branch_type"],
                            b["block_type"],
                            b["flags"],
                            b["dominators"],
                            b["post_dominators"],
                            now,
                        ]
                        # Flatten: iterate through all functions, then all blocks in each function
                        for func_cfg in self.analysis_results["cfg"]
                        if func_cfg is not None  # Handle None from failed extractions
                        for b in func_cfg["blocks"]
                    ],
                    "column_names": [
                        "block_id",
                        "sha256",
                        "sha1",
                        "md5",
                        "function_address",
                        "block_start_address",
                        "block_end_address",
                        "block_size",
                        "instructions_count",
                        "block_instructions_hash",
                        "predecessor_blocks",
                        "successor_blocks",
                        "depth",
                        "position",
                        "branch_type",
                        "block_type",
                        "flags",
                        "dominators",
                        "post_dominators",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",  # block_id (SHA256)
                        "FixedString(64)",  # sha256
                        "FixedString(40)",  # sha1
                        "FixedString(32)",  # md5
                        "UInt64",  # function_address
                        "UInt64",  # block_start_address
                        "UInt64",  # block_end_address
                        "UInt32",  # block_size
                        "UInt16",  # instructions_count
                        "FixedString(32)",  # block_instructions_hash (MD5)
                        "Array(UInt64)",  # predecessor_blocks
                        "Array(UInt64)",  # successor_blocks
                        "UInt16",  # depth
                        "UInt16",  # position
                        "Enum8('DIRECT'=1, 'CONDITIONAL'=2, 'CALL'=3, 'RETURN'=4, 'FALLTHROUGH'=5, 'INDIRECT'=6, 'UNKNOWN'=7)",  # branch_type
                        "Enum8('CODE'=1, 'DATA'=2, 'THUNK'=3)",  # block_type
                        "Array(String)",  # flags (EntryBlock, ExitBlock, LoopBlock)
                        "Array(UInt16)",  # dominators
                        "Array(UInt16)",  # post_dominators
                        "DateTime64(3, 'UTC')",  # analysis_date
                    ],
                },
                "function_analysis_errors": {
                    "table": "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['error_message']}{f['function_name']}{f['function_address']}{f['error_location']}"
                            ),
                            "new",
                            now,
                        ]
                        for f in self.analysis_results["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')",
                    ],
                },
            }

    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

    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()

    # Create and run the extractor
    with DecompileBinja(args.filepath, logger) as extractor:
        success = extractor.extract()

        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(json.dumps(extractor.analysis_results))