Xianghua Xie

180 papers A* 4A 11B 26C 3Misc 2Journal 80Unranked 52
YearRankTypeTitle / Venue / Authors
2026 J jnl
Robotics Auton. Syst.
Daniele Cafolla, Betsy Dayana Marcela Chaparro Rico, Xianghua Xie
2026 J jnl
Eng. Appl. Artif. Intell.
Fanzhi Jiang, Kexin Wang, Hanchi Ren, Yiming Li, Liumei Zhang, Yuanjiao Hu, Xianghua Xie, Su Yang
2025 B conf
ACIVS
Connor Clarkson, Michael Edwards, Xianghua Xie
2025 J jnl
SN Comput. Sci.
Majedaldein Almahasneh, Xianghua Xie, Adeline Paiement
2025 conf
AIiH (2)
Vasiles Balabanis, Jiaxiang Zhang, Xianghua Xie, Su Yang
2025 J jnl
Pattern Recognit.
Yifan Wang, Gerald Schaefer, Xiyao Liu, Jing Dong, Linglin Jing, Ye Wei, Xianghua Xie, Hui Fang
2025 A* conf
IJCAI
Chen Hu, Hanchi Ren, Jingjing Deng, Xianghua Xie, Xiaoke Ma
2025 J jnl
CoRR
Yi Hu, Hanchi Ren, Jingjing Deng, Xianghua Xie
2025 conf
AIiH (2)
Ali Guran, Avishek Siris, Gary K. L. Tam, James Chess, Xianghua Xie
2025 J jnl
Neural Networks
Zengfa Dou, Nian Peng, Weiming Hou, Xianghua Xie, Xiaoke Ma
2025 B conf
ACIVS
Alexander J. M. Milne, Xianghua Xie, Gary K. L. Tam
2025 J jnl
Int. J. Digit. Earth
Xianghua Xie, Yingquan Yang, Yining Wang, Lingling Yan, Bihong Fu, Liang Chang
2025 conf
AIiH (2)
Hanchi Ren, Jingjing Deng, Xianghua Xie, Xiaoke Ma, Jianfeng Ma
2025 J jnl
IET Image Process.
Yaxian Gao, Zhaoyuan Cai, Xianghua Xie, Jingjing Deng, Zengfa Dou, Xiaoke Ma
2025 B conf
ACIVS
Nurhan Bulus Guran, Hanchi Ren, Jingjing Deng, Xianghua Xie
2025 J jnl
IET Comput. Vis.
Rosie Finnegan, Joseph Metcalfe, Sara Sharifzadeh, Fabio Caraffini, Xianghua Xie, Alberto Hornero, Nicholas W. Synes
2024 J jnl
Neurocomputing
Xianghua Xie, Chen Hu, Hanchi Ren, Jingjing Deng
2024 J jnl
CoRR
Yi Hu, Hanchi Ren, Chen Hu, Jingjing Deng, Xianghua Xie
2024 ed.
AIiH (1)
Xianghua Xie, Iain B. Styles, Gibin G. Powathil, Marco Ceccarelli
2024 ed.
AIiH (2)
Xianghua Xie, Iain B. Styles, Gibin G. Powathil, Marco Ceccarelli
2024 J jnl
CoRR
Majedaldein Almahasneh, Xianghua Xie, Adeline Paiement
2024 conf
AIiH (1)
Suraj Ramchand, Xianghua Xie
2024 J jnl
CoRR
Deyin Liu, Lin Yuanbo Wu, Xianghua Xie
2024 conf
ISBI
Yiming Li, Hanchi Ren, Jingjing Deng, Xiaoke Ma, Xianghua Xie
2024 conf
AIiH (1)
Fergus Pick, Xianghua Xie, Lin Yuanbo Wu
2024 conf
MICCAI (6)
Francis Xiatian Zhang, Shuang Chen, Xianghua Xie, Hubert P. H. Shum
2024 J jnl
CoRR
Francis Xiatian Zhang, Shuang Chen, Xianghua Xie, Hubert P. H. Shum
2024 J jnl
CoRR
Chen Hu, Hanchi Ren, Jingjing Deng, Xianghua Xie
2024 J jnl
Neurocomputing
Hanchi Ren, Jingjing Deng, Xianghua Xie, Xiaoke Ma, Yichuan Wang
2024 J jnl
CoRR
Chen Hu, Jingjing Deng, Xianghua Xie, Xiaoke Ma
2024 J jnl
IEEE Trans. Neural Networks Learn. Syst.
Hassan Eshkiki, Benjamin Mora, Xianghua Xie
2024 J jnl
IEEE Trans. Emerg. Top. Comput. Intell.
Yun Ai, Xianghua Xie, Xiaoke Ma
2024 J jnl
IET Image Process.
Zhaoyuan Cai, Xianghua Xie, Jingjing Deng, Zengfa Dou, Bo Tong, Xiaoke Ma
2024 J jnl
CoRR
Junhui Yin, Xinyu Zhang, Lin Wu, Xianghua Xie, Xiaojie Wang
2024 J jnl
Int. J. Comput. Vis.
Avishek Siris, Jianbo Jiao, Gary K. L. Tam, Xianghua Xie, Rynson W. H. Lau
2024 J jnl
Pattern Recognit.
Deyin Liu, Lin Yuanbo Wu, Bo Li, Farid Boussaïd, Mohammed Bennamoun, Xianghua Xie, Chengwu Liang
2024 J jnl
CoRR
Majedaldein Almahasneh, Adeline Paiement, Xianghua Xie, Jean Aboudarham
2024 J jnl
CoRR
Felix Richards, Adeline Paiement, Xianghua Xie, Elisabeth Sola, Pierre-Alain Duc
2024 conf
AIiH (1)
Ali Guran, Gary K. L. Tam, James Chess, Xianghua Xie
2024 J jnl
CoRR
Felix Richards, Adeline Paiement, Xianghua Xie, Elisabeth Sola, Pierre-Alain Duc
2024 J jnl
CoRR
Nurhan Bulus Guran, Hanchi Ren, Jingjing Deng, Xianghua Xie
2024 J jnl
CoRR
Yiming Li, Hanchi Ren, Jingjing Deng, Xianghua Xie
2023 J jnl
CoRR
Xianghua Xie, Chen Hu, Hanchi Ren, Jingjing Deng
2023 conf
EICS (Companion)
Connor Clarkson, Michael Edwards, Xianghua Xie
2023 conf
ICDM (Workshops)
Yi Hu, Hanchi Ren, Chen Hu, Jingjing Deng, Xianghua Xie
2023 J jnl
Image Vis. Comput.
Chen Hu, Xianghua Xie, Lin Wu
2023 J jnl
CoRR
Hanchi Ren, Jingjing Deng, Xianghua Xie, Xiaoke Ma, Jianfeng Ma
2023 conf
ISBI
Sachin Bahade, Michael Edwards, Xianghua Xie
2023 A conf
ICME
Bo Li, Lin Yuanbo Wu, Deyin Liu, Hongyang Chen, Yuanxin Ye, Xianghua Xie
2023 J jnl
IEEE Trans. Image Process.
Lin Wu, Lingqiao Liu, Yang Wang, Zheng Zhang, Farid Boussaïd, Mohammed Bennamoun, Xianghua Xie
2023 Misc conf
MVA
Felix Richards, Adeline Paiement, Xianghua Xie, Elisabeth Sola, Pierre-Alain Duc
2023 J jnl
CoRR
Alexander J. M. Milne, Xianghua Xie
2023 J jnl
CoRR
Alexander J. M. Milne, Xianghua Xie
2022 J jnl
Comput. Aided Des.
David George, Xianghua Xie, Yu-Kun Lai, Gary K. L. Tam
2022 J jnl
Pattern Recognit. Lett.
Michael P. Kenning, Jingjing Deng, Michael Edwards, Xianghua Xie
2022 J jnl
IET Image Process.
Zengfa Dou, Xiaoke Ma, Xianghua Xie, Hui Liu, Chubing Guo
2022 J jnl
ACM Trans. Intell. Syst. Technol.
Hanchi Ren, Jingjing Deng, Xianghua Xie
2022 J jnl
Pattern Recognit.
Xiaoke Ma, Shiyin Tan, Xianghua Xie, Xiaoxiong Zhong, Jingjing Deng
2022 J jnl
Mach. Vis. Appl.
Majedaldein Almahasneh, Adeline Paiement, Xianghua Xie, Jean Aboudarham
2022 J jnl
SN Comput. Sci.
Majedaldein Almahasneh, Adeline Paiement, Xianghua Xie, Jean Aboudarham
2022 B conf
ICIP
Felix Richards, Xianghua Xie, Adeline Paiement, Elisabeth Sola, Pierre-Alain Duc
2022 conf
ICPRAI (2)
Chen Hu, Xianghua Xie
2022 conf
BHI
Suraj Ramchand, Gavin Tsang, Duncan Cole, Xianghua Xie
2021 J jnl
IEEE Trans. Image Process.
Jingjing Deng, Xianghua Xie
2021 C conf
ICPRAM
Majedaldein Almahasneh, Adeline Paiement, Xianghua Xie, Jean Aboudarham
2021 J jnl
IEEE Access
Ehab Essa, Xianghua Xie
2021 J jnl
CoRR
Hanchi Ren, Jingjing Deng, Xianghua Xie
2021 C conf
ICPRAM
Sachin Bahade, Michael Edwards, Xianghua Xie
2021 J jnl
IEEE Access
Stavros Georgousis, Michael P. Kenning, Xianghua Xie
2021 J jnl
Informatics
Ali Alqahtani, Xianghua Xie, Mark W. Jones
2021 C conf
ICPRAM
Michael P. Kenning, Jingjing Deng, Michael Edwards, Xianghua Xie
2021 J jnl
Comput. Vis. Image Underst.
Ali Alqahtani, Xianghua Xie, Mark W. Jones, Ehab Essa
2021 A* conf
ICCV
Avishek Siris, Jianbo Jiao, Gary K. L. Tam, Xianghua Xie, Rynson W. H. Lau
2021 J jnl
BMC Bioinform.
Yan Wang, Zuheng Xia, Jingjing Deng, Xianghua Xie, Maoguo Gong, Xiaoke Ma
2020 J jnl
Appl. Soft Comput.
Huaizhong Zhang, Ehab Essa, Xianghua Xie
2020 B conf
ICPR
Gavin Tsang, Xianghua Xie
2020 J jnl
Comput. Vis. Image Underst.
Michael Edwards, Xianghua Xie, Robert Ieuan Palmer, Gary K. L. Tam, Rob Alcock, Carl Roobottom
2020 A* conf
CVPR
Avishek Siris, Jianbo Jiao, Gary K. L. Tam, Xianghua Xie, Rynson W. H. Lau
2020 J jnl
CoRR
Felix Richards, Adeline Paiement, Xianghua Xie, Pierre-Alain Duc
2020 conf
EUSIPCO
Ehab Essa, Xianghua Xie
2020 B conf
ICPR
Ali Alqahtani, Xianghua Xie, Ehab Essa, Mark W. Jones
2020 J jnl
CoRR
Hanchi Ren, Jingjing Deng, Xianghua Xie
2020 B conf
ICPR
Lee Au-Yeung, Xianghua Xie, James Chess, Timothy Scale
2019 J jnl
IEEE Access
Mohammed Ali, Ali Alqahtani, Mark W. Jones, Xianghua Xie
2019 J jnl
Comput. Aided Geom. Des.
Taiwei Wang, David George, Yu-Kun Lai, Xianghua Xie, Gary K. L. Tam
2019 conf
ICVISP
Alex Momotov, Xianghua Xie
2019 conf
CAIP (1)
Ali Alqahtani, Xianghua Xie, Jingjing Deng, Mark W. Jones
2019 conf
CGVC
Taiwei Wang, Kristiyan Vladimirov, Shu Yu Goh, Yu-Kun Lai, Xianghua Xie, Gary K. L. Tam
2019 J jnl
Vis. Comput.
Mohammed Ali, Mark W. Jones, Xianghua Xie, Mark Williams
2018 J jnl
Graph. Model.
David George, Xianghua Xie, Gary K. L. Tam
2018 B conf
ICIP
Ali Alqahtani, Xianghua Xie, Jingjing Deng, Mark W. Jones
2018 J jnl
CoRR
David George, Xianghua Xie, Yu-Kun Lai, Gary K. L. Tam
2018 B conf
ICIP
Michael P. Kenning, Xianghua Xie, Michael Edwards, Jingjing Deng
2018 conf
MIUA
Paul Stroe, Xianghua Xie, Adeline Paiement
2018 B conf
ICPR
Gavin Tsang, Jingjing Deng, Xianghua Xie
2018 conf
BDVA
Mohammed Ali, Mark W. Jones, Xianghua Xie, Mark Williams
2017 J jnl
CoRR
David George, Xianghua Xie, Gary K. L. Tam
2017 B conf
ACIVS
Dafydd Ravenscroft, Jingjing Deng, Xianghua Xie, Louise Terry, Tom H. Margrain, Rachel V. North, Ashley Wood
2017 J jnl
Comput. methods Biomech. Biomed. Eng. Imaging Vis.
Igor Sazonov, Xianghua Xie, Perumal Nithiarasu
2017 J jnl
Comput. Vis. Image Underst.
Ehab Essa, Xianghua Xie
2017 B conf
ICIP
Jingjing Deng, Xianghua Xie
2017 conf
PerCom Workshops
Michael Edwards, Jingjing Deng, Xianghua Xie
2017 conf
EUSIPCO
Dafydd Ravenscroft, Jingjing Deng, Xianghua Xie, Louise Terry, Tom H. Margrain, Rachel V. North, Ashley Wood
2017 B conf
FG
Jingjing Deng, Xianghua Xie
2017 J jnl
Int. J. Comput. Vis.
Xianghua Xie, Mark W. Jones, Gary K. L. Tam
2016 conf
ICIAR
Jingjing Deng, Xianghua Xie, Louise Terry, Ashley Wood, Nick S. White, Tom H. Margrain, Rachel V. North
2016 B conf
ACIVS
Jingjing Deng, Xianghua Xie, Michael Edwards
2016 conf
ICIAR
Ehab Essa, Xianghua Xie, Richard Turner, Matthew Stevens, Daniel Power
2016 J jnl
Image Vis. Comput.
Ben Daubney, Xianghua Xie, Jingjing Deng, Neil Mac Parthaláin, Reyer Zwiggelaar
2016 J jnl
Comput. Vis. Image Underst.
Michael Edwards, Jingjing Deng, Xianghua Xie
2016 J jnl
CoRR
Michael Edwards, Xianghua Xie
2016 A conf
BMVC
Michael Edwards, Xianghua Xie
2016 conf
ICIAR
Jonathan-Lee Jones, Xianghua Xie
2016 B conf
ACIVS
Robert Ieuan Palmer, Xianghua Xie
2016 J jnl
IEEE Trans. Image Process.
Adeline Paiement, Majid Mirmehdi, Xianghua Xie, Mark C. K. Hamilton
2015 conf
EMBC
Ehab Essa, Xianghua Xie, Rachel J. Errington, Nick S. White
2015 A conf
BMVC
Robert Ieuan Palmer, Xianghua Xie, Gary K. L. Tam
2015 conf
EMBC
Jonathan-Lee Jones, Ehab Essa, Xianghua Xie
2015 conf
MIUA
Robert Ieuan Palmer, Gary K. L. Tam, Xianghua Xie, Rob Alcock, Carl Roobottom
2015 J jnl
IEEE Trans. Image Process.
Huaizhong Zhang, Xianghua Xie
2015 conf
EMBC
Robert Ieuan Palmer, Xianghua Xie, Gary K. L. Tam
2015 J jnl
CoRR
Michael Edwards, Jingjing Deng, Xianghua Xie
2015 conf
GbRPR
Ehab Essa, Xianghua Xie, Jonathan-Lee Jones
2015 conf
MICCAI (2)
Ehab Essa, Xianghua Xie, Jonathan-Lee Jones
2015 A ed.
BMVC
Xianghua Xie, Mark W. Jones, Gary K. L. Tam
2014 B conf
ICIP
Jingjing Deng, Xianghua Xie, Rob Alcock, Carl Roobottom
2014 J jnl
Graph. Model.
Jingjing Deng, Xianghua Xie, Ben Daubney
2014 conf
EUSIPCO
David James, Xianghua Xie, Parisa Eslambolchilar
2014 conf
ISBI
Huaizhong Zhang, Xianghua Xie
2014 conf
ICIAR (1)
Jingjing Deng, Xianghua Xie, Shang-Ming Zhou
2014 conf
BMEI
Michael Edwards, Xianghua Xie
2014 J jnl
IEEE Trans. Image Process.
Adeline Paiement, Majid Mirmehdi, Xianghua Xie, Mark C. K. Hamilton
2014 conf
BMEI
Arron Lacey, Jingjing Deng, Xianghua Xie
2013 B conf
ICIP
Hui Fang, Jingjing Deng, Xianghua Xie, Philip W. Grant
2013 B conf
ICIP
Huaizhong Zhang, Ehab Essa, Xianghua Xie
2013 conf
CAIP (2)
Jonathan-Lee Jones, Ehab Essa, Xianghua Xie, Dave Smith
2013 B conf
ACIVS
Jingjing Deng, Xianghua Xie, Ben Daubney, Hui Fang, Phil W. Grant
2013 J jnl
IET Comput. Vis.
Ronghua Yang, Majid Mirmehdi, Xianghua Xie, David Hall
2012 J jnl
IEEE Trans. Image Process.
John Chiverton, Xianghua Xie, Majid Mirmehdi
2012 conf
MCV
Igor Sazonov, Xianghua Xie, Perumal Nithiarasu
2012 conf
ICPRAM (2)
Zhiqiang Hou, Sion L. Hannuna, Xianghua Xie, Majid Mirmehdi
2012 conf
ICPRAM (1)
Si Yong Yeo, Xianghua Xie, Igor Sazonov, Perumal Nithiarasu
2012 conf
MCV
Ehab Essa, Xianghua Xie, Igor Sazonov, Perumal Nithiarasu, Dave Smith
2012 J jnl
Comput. Graph. Forum
Rita Borgo, Min Chen, Ben Daubney, Edward Grundy, Gunther Heidemann, Benjamin Höferlin, Markus Höferlin, Heike Leitte, Daniel Weiskopf, Xianghua Xie
2011 conf
Eurographics (State of the Art Reports)
Rita Borgo, Min Chen, Ben Daubney, Edward Grundy, Gunther Heidemann, Benjamin Höferlin, Markus Höferlin, Heike Jänicke, Daniel Weiskopf, Xianghua Xie
2011 B conf
ICIP
Ehab Essa, Xianghua Xie, Igor Sazonov, Perumal Nithiarasu
2011 conf
MIUA
Ehab Essa, Xianghua Xie, Igor Sazonov, Perumal Nithiarasu, Dave Smith
2011 A conf
BMVC
Ben Daubney, Xianghua Xie
2011 J jnl
IEEE Trans. Image Process.
Si Yong Yeo, Xianghua Xie, Igor Sazonov, Perumal Nithiarasu
2011 B conf
ICIP
Si Yong Yeo, Xianghua Xie, Igor Sazonov, Perumal Nithiarasu
2011 J jnl
Image Vis. Comput.
Xianghua Xie, Majid Mirmehdi
2011 A* conf
CVPR
Ben Daubney, Xianghua Xie
2010 J jnl
IEEE Trans. Image Process.
Xianghua Xie
2010 B conf
ICPR
Ben Daubney, Xianghua Xie
2010 conf
AMDO
Ben Daubney, Xianghua Xie
2010 conf
ECCV (4)
V. Javier Traver, Majid Mirmehdi, Xianghua Xie, Raúl Montoliu
2010 B conf
ICPR
Xianghua Xie, Majid Mirmehdi
2010 B conf
ICPR
Xianghua Xie
2009 conf
VISAPP (2)
Sion L. Hannuna, Xianghua Xie, Majid Mirmehdi, Neill W. Campbell
2009 A conf
BMVC
Si Yong Yeo, Xianghua Xie, Igor Sazonov, Perumal Nithiarasu
2009 Misc conf
IbPRIA
Filiberto Pla, Gema Gracia, Pedro García-Sevilla, Majid Mirmehdi, Xianghua Xie
2009 A conf
BMVC
John Chiverton, Majid Mirmehdi, Xianghua Xie
2009 conf
CIRA
Yonghuai Liu, Longzhuang Li, Xianghua Xie, Baogang Wei
2009 conf
VISIGRAPP (Selected Papers)
Xianghua Xie
2009 conf
VISAPP (1)
Xianghua Xie
2008 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Xianghua Xie, Majid Mirmehdi
2008 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Xianghua Xie, Majid Mirmehdi
2008 A conf
BMVC
John Chiverton, Xianghua Xie, Majid Mirmehdi
2008 B conf
ICPR
John Chiverton, Majid Mirmehdi, Xianghua Xie
2007 A conf
BMVC
Xianghua Xie, Majid Mirmehdi
2007 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Xianghua Xie, Majid Mirmehdi
2006 B conf
ACIVS
Ronghua Yang, Majid Mirmehdi, Xianghua Xie
2006 J jnl
Mach. Vis. Appl.
Xianghua Xie, Majid Mirmehdi, Barry T. Thomas
2006 A conf
BMVC
Xianghua Xie, Majid Mirmehdi
2005 conf
ICIP (3)
Xianghua Xie, Majid Mirmehdi
2005 conf
ICAPR (2)
Xianghua Xie, Majid Mirmehdi
2004 conf
ICIAR (2)
Xianghua Xie, Majid Mirmehdi, Barry T. Thomas
2004 J jnl
IEEE Trans. Image Process.
Xianghua Xie, Majid Mirmehdi
2003 A conf
BMVC
Xianghua Xie, Majid Mirmehdi
2003 conf
ICIP (2)
Xianghua Xie, Majid Mirmehdi
redb/extractors/decompiler/_archive/DecompileGhidra.py
← Index redb/extractors/decompiler/_archive/DecompileGhidra.py python
from hashlib import sha256, md5
import inspect
import subprocess
import json
import os
import time
from datetime import datetime, timezone
from typing import Dict, List, Any, Optional

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


class DecompileGhidra(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)
        self.ghidra_path = os.getenv("GHIDRA_PATH", "/opt/ghidra")
        self.java_script_path = os.getenv(
            "GHIDRA_SCRIPT_PATH",
            "/opt/ghidra/Ghidra/Features/Base/ghidra_scripts/GhidraDecompilerScript.java",
        )
        self.analysis_results = None
        self.ghidra_process = None  # Track the current process
        self.project_path = None
        self.filetype = filetype

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

        self.initialize_project()

    def __enter__(self):
        return self

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

    def is_dotnet(self):
        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:
            if self.ghidra_process and self.ghidra_process.poll() is None:
                self.ghidra_process.terminate()
                try:
                    self.ghidra_process.wait(timeout=5)
                except subprocess.TimeoutExpired:
                    self.ghidra_process.kill()

            # Clean up project directory
            if self.project_path and os.path.exists(self.project_path):
                import shutil

                shutil.rmtree(self.project_path)
                self.log.debug(f"Cleaned up project directory: {self.project_path}")

            # Force garbage collection
            import gc

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

    # @classmethod
    # def cleanup_batch(cls):
    #     """Clean up the persistent project at the end of a batch."""
    #     print(f"Cleaning up Ghidra project for batch")
    #     if cls._project_path and os.path.exists(cls._project_path):
    #         try:
    #             import shutil
    #             shutil.rmtree(cls._project_path)
    #             cls._project_initialized = False
    #             cls._project_path = None
    #         except Exception as e:
    #             print(f"Error cleaning up project: {e}")

    def _get_environment(self):
        """Setup and return the environment for Ghidra."""
        env = os.environ.copy()
        java_home = os.getenv("GHIDRA_JAVA_HOME", "/usr/lib/jvm/java-17-openjdk-amd64")
        env.update(
            {
                "JAVA_HOME": java_home,
                "PATH": f"{java_home}/bin:{env['PATH']}",
                "LD_LIBRARY_PATH": f"{java_home}/lib:{env.get('LD_LIBRARY_PATH', '')}",
            }
        )
        # Print environment variables for debugging
        self.log.debug(f"JAVA_HOME: {env['JAVA_HOME']}")
        self.log.debug(f"PATH: {env['PATH']}")
        self.log.debug(f"LD_LIBRARY_PATH: {env['LD_LIBRARY_PATH']}")

        return env

    def initialize_project(self):
        """Initialize a temporary Ghidra project for this file."""
        # Create unique project directory
        self.project_path = f"/tmp/ghidra_{os.path.basename(self.filepath)}_{str(int(time.time()))}_{os.getpid()}"
        os.makedirs(self.project_path, exist_ok=True)
        self.log.debug(f"Created temporary project at {self.project_path}")

        # Create a minimal initialization file
        init_file = os.path.join(self.project_path, ".init")
        with open(init_file, "wb") as f:
            f.write(bytes([0x7F, 0x45, 0x4C, 0x46]))  # Valid ELF header magic bytes

        # Initialize project with minimal file
        env = self._get_environment()
        cmd = [
            f"{self.ghidra_path}/support/analyzeHeadless",
            self.project_path,
            "TempProject",
            "-import",
            init_file,
        ]

        try:
            result = subprocess.run(cmd, env=env, capture_output=True, text=True)
            if result.returncode != 0:
                self.log.error(f"Failed to initialize project: {result.stderr}")
                raise RuntimeError("Project initialization failed")

            # Clean up initialization file
            os.remove(init_file)
            self.log.debug("Project initialized successfully")

        except Exception as e:
            self.log.error(f"Error initializing project: {e}")
            raise

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

        # # Check if packed
        # if self.check_binary_protection():
        #     self.log.warning("Skipping protected binary")
        #     return None

        # Check for .NET only if needed
        # if self.is_dotnet():
        #     self.MAX_NAMED_ARG_WARNINGS = 10000  # Higher threshold for .NET
        #     self.log.info("Adjusting parameters for .NET binary")
        # else:
        #     self.MAX_NAMED_ARG_WARNINGS = 1000  # Normal threshold

        if not os.path.exists(self.java_script_path):
            self.log.error(f"Java script not found: {self.java_script_path}")
            return None

        env = self._get_environment()

        try:
            base_cmd = [
                f"{self.ghidra_path}/support/analyzeHeadless",
                self.project_path,
                "TempProject",
                "-import",
                self.filepath,
                "-scriptPath",
                os.path.dirname(self.java_script_path),
                "-postScript",
                self.java_script_path,
                self.sha256,
                self.filepath,
            ]
            return self.run_ghidra(base_cmd, env)

        except Exception as e:
            self.log.error(f"Error in Ghidra analysis: {e}")
            return None

        finally:
            self.cleanup_run()

    def run_ghidra(
        self, cmd: list, env: Optional[Dict[str, str]] = None
    ) -> Optional[Dict[str, Any]]:
        """Run Ghidra process and capture JSON output with improved logging separation."""
        process = None
        try:
            self.log.info(f"Starting Ghidra analysis: {' '.join(cmd)}")
            start_time = time.time()

            process = subprocess.Popen(
                cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
            )
            self.ghidra_process = process

            warning_counter = 0
            named_arg_counter = 0
            # Read all output lines
            json_output = None
            while True:
                line = process.stdout.readline()
                if not line and process.poll() is not None:
                    break

                stripped_line = line.strip()
                if not stripped_line:
                    continue

                # if 'Invalid FieldOrProp value in NamedArg' in stripped_line:
                #     named_arg_counter += 1
                #     if named_arg_counter > self.MAX_NAMED_ARG_WARNINGS:
                #         self.log.error(f"Too many NamedArg warnings ({named_arg_counter}), possible protected file.")
                #         self.ghidra_process.kill()
                #         return None
                if (
                    stripped_line.startswith("{")
                    and '"sha256"' in stripped_line
                    and '"decompiled"' in stripped_line
                ):
                    # This is our actual JSON output from GhidraDecompilerScript
                    json_output = stripped_line
                elif any(level in stripped_line for level in ["INFO", "WARN", "ERROR"]):
                    # Ghidra framework logging
                    log_level = (
                        "debug"
                        if "INFO" in stripped_line
                        else "warning"
                        if "WARN" in stripped_line
                        else "error"
                    )
                    if log_level == "warning" and any(
                        expected in stripped_line
                        for expected in [
                            "Unable to disassemble EXTERNAL block",
                            "Failed to markup ELF Note",
                            "Invalid FieldOrProp value in NamedArg",
                            "Unable to resolve constructor",
                            "Could not follow disassembly flow into non-existing memory",
                            "Unable to read bytes at ram",
                        ]
                    ):
                        # Skip expected warnings
                        continue

                    getattr(self.log, log_level)(f"Ghidra info: {stripped_line}")

            # Process completion and stderr
            try:
                stderr = process.stderr.read()
                process.wait(timeout=self.TIMEOUT)

                if stderr:
                    for line in stderr.splitlines():
                        stripped_line = line.strip()
                        if not stripped_line:
                            continue
                        if "ERROR" in stripped_line:
                            self.log.error(f"Ghidra stderr: {stripped_line}")
                        elif "WARN" in stripped_line:
                            self.log.warning(f"Ghidra stderr: {stripped_line}")
                        else:
                            self.log.debug(f"Ghidra stderr: {stripped_line}")

            except subprocess.TimeoutExpired:
                process.kill()
                self.log.error("Ghidra analysis timed out")
                return None

            elapsed_time = time.time() - start_time
            self.log.debug(f"Ghidra analysis completed in {elapsed_time:.2f}s")

            # Parse JSON output if we found it
            if json_output:
                try:
                    result = json.loads(json_output)
                    # Validate the required structure
                    if not isinstance(result, dict) or not all(
                        k in result
                        for k in ["sha256", "decompiled", "disassembled", "cfg"]
                    ):
                        self.log.error("Invalid JSON structure from Ghidra")
                        return None
                    return result
                except json.JSONDecodeError as e:
                    self.log.error(f"Failed to parse Ghidra JSON output: {e}")
                    return None
            else:
                self.log.error("No JSON output received from Ghidra")
                return None

        except Exception as e:
            self.log.error(f"Error running Ghidra: {str(e)}")
            if hasattr(e, "__traceback__"):
                import traceback

                self.log.debug(
                    f"Traceback: {''.join(traceback.format_tb(e.__traceback__))}"
                )
            return None

        finally:
            if process:
                try:
                    # Ensure pipes are closed
                    if process.stdout:
                        process.stdout.close()
                    if process.stderr:
                        process.stderr.close()
                    # Terminate process if still running
                    if process.poll() is None:
                        process.terminate()
                        try:
                            process.wait(timeout=5)
                        except subprocess.TimeoutExpired:
                            process.kill()
                except Exception as e:
                    self.log.error(f"Error cleaning up Ghidra process: {e}")

    def extract(self) -> bool:
        """Extract and process all analysis results."""
        self.log.debug(inspect.currentframe().f_code.co_name)
        try:
            results = self.analyze_binary()
            if not results:
                return False

            self.analysis_results = results
            return True

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

    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

        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

            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": "decompiled_functions_content",
                    "data": [
                        [
                            f["decompiled_content_hash"],
                            f["decompiled_function"],
                            f["function_type"],
                            now,
                        ]
                        for f in self.analysis_results["decompiled"]
                    ],
                    "column_names": [
                        "decompiled_content_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": "decompiled_functions_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f["decompiled_content_hash"],
                            f["decompiled_function_name"],
                            f["decompiled_function_address"],
                            now,
                        ]
                        for f in self.analysis_results["decompiled"]
                    ],
                    "column_names": [
                        "sha256",
                        "decompiled_content_hash",
                        "decompiled_function_name",
                        "decompiled_function_address",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(64)",
                        "LowCardinality(String)",
                        "String",
                        "DateTime64(3, 'UTC')",
                    ],
                },
                "disassembled_content": {
                    "table": "disassembled_functions_content",
                    "data": [
                        [
                            f["disassembled_content_hash"],
                            f["fully_normalized_content_hash"],
                            f["api_normalized_content_hash"],
                            f["category_normalized_content_hash"],
                            f.get("disassembled_function", ""),
                            f.get("fully_normalized_disassembly", ""),
                            f.get("api_normalized_disassembly", ""),
                            f.get("category_normalized_disassembly", ""),
                            ssdeep_disassembly(f.get("disassembled_function", "")),
                            tlsh_disassembly(f.get("disassembled_function", "")),
                            ssdeep_disassembly(
                                f.get("fully_normalized_disassembly", "")
                            ),
                            tlsh_disassembly(f.get("fully_normalized_disassembly", "")),
                            f.get("function_type", "UNKNOWN"),
                            f.get("instruction_count", 0),
                            prepare_array_field(
                                f.get("instruction_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),
                            # prepare_array_field(f.get('opcode_frequency_vector'), 'Float32'),
                            # prepare_array_field(f.get('api_calls_vector'), 'Float32'),
                            # prepare_array_field(f.get('minhash_signature'), 'UInt64'),
                            # f.get('pic_hash', ''),
                            f.get("max_block_size", 0),
                            f.get("num_calls", 0),
                            f.get("stack_size", 0),
                            # prepare_array_field(f.get('instruction_type_ratios'), 'Float32'),
                            # prepare_array_field(f.get('instruction_embedding'), 'Float32'),
                            now,
                        ]
                        for f in self.analysis_results["disassembled"]
                    ],
                    "column_names": [
                        "disassembled_content_hash",
                        "fully_normalized_content_hash",
                        "api_normalized_content_hash",
                        "category_normalized_content_hash",
                        "disassembled_function",
                        "fully_normalized_disassembly",
                        "api_normalized_disassembly",
                        "category_normalized_disassembly",
                        "ssdeep_disassembly",
                        "tlsh_disassembly",
                        "ssdeep_fully_normalized",
                        "tlsh_fully_normalized",
                        "function_type",
                        "instruction_count",
                        "instruction_types",
                        "control_flow_count",
                        "memory_access_pattern",
                        "register_usage",
                        "data_references_count",
                        # 'opcode_frequency_vector',
                        # 'api_calls_vector',
                        # 'minhash_signature',
                        # 'pic_hash',
                        "max_block_size",
                        "num_calls",
                        "stack_size",
                        # 'instruction_type_ratios',
                        # 'instruction_embedding',
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(64)",
                        "FixedString(64)",
                        "FixedString(64)",
                        "String",
                        "String",
                        "String",
                        "String",
                        "Nullable(String)",
                        "Nullable(FixedString(72))",
                        "Nullable(String)",
                        "Nullable(FixedString(72))",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'THUNK'=3, 'EXTERNAL'=4, 'UNKNOWN'=5)",
                        "UInt32",
                        "Array(LowCardinality(String))",
                        "UInt32",
                        "Array(LowCardinality(String))",
                        "Array(LowCardinality(String))",
                        "UInt32",
                        # 'Array(Float32)',
                        # 'Array(Float32)',
                        # 'Array(UInt64)',
                        # 'Nullable(FixedString(16))',
                        "Nullable(UInt32)",
                        "Nullable(UInt32)",
                        "Nullable(Int32)",
                        # 'Array(Float32)',
                        # 'Array(Float32)',
                        "DateTime64(3, 'UTC')",
                    ],
                },
                "disassembled_refs": {
                    "table": "disassembled_functions_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f["disassembled_content_hash"],
                            f["fully_normalized_content_hash"],
                            f["api_normalized_content_hash"],
                            f["category_normalized_content_hash"],
                            f["disassembled_function_name"],
                            f["disassembled_function_address"],
                            now,
                        ]
                        for f in self.analysis_results["disassembled"]
                    ],
                    "column_names": [
                        "sha256",
                        "disassembled_content_hash",
                        "fully_normalized_content_hash",
                        "api_normalized_content_hash",
                        "category_normalized_content_hash",
                        "disassembled_function_name",
                        "disassembled_function_address",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(64)",
                        "FixedString(64)",
                        "FixedString(64)",
                        "FixedString(64)",
                        "LowCardinality(String)",
                        "String",
                        "DateTime64(3, 'UTC')",
                    ],
                },
                "cfg_blocks": {
                    "table": "cfg_blocks",
                    "data": [
                        [
                            b["block_id"],
                            self.analysis_results["sha256"],
                            b["function_address"],
                            b["block_start_address"],
                            b["block_end_address"],
                            b["block_size"],
                            b["block_instructions"],
                            b["fully_normalized_instructions"],
                            b["api_normalized_instructions"],
                            b["category_normalized_instructions"],
                            b.get("predecessor_blocks", []),
                            b.get("successor_blocks", []),  # Use empty array as default
                            b.get("is_entry_block", False),
                            b.get("is_exit_block", False),
                            b.get("branch_type", "UNKNOWN"),
                            b.get("referenced_constants", []),
                            b.get("sign", 1),  # Use 1 as default for sign
                            now,
                        ]
                        for b in self.analysis_results["cfg"]
                    ],
                    "column_names": [
                        "block_id",
                        "sha256",
                        "function_address",
                        "block_start_address",
                        "block_end_address",
                        "block_size",
                        "block_instructions",
                        "fully_normalized_instructions",
                        "api_normalized_instructions",
                        "category_normalized_instructions",
                        "predecessor_blocks",
                        "successor_blocks",
                        "is_entry_block",
                        "is_exit_block",
                        "branch_type",
                        "referenced_constants",
                        "sign",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(64)",
                        "String",
                        "String",
                        "String",
                        "UInt32",
                        "String",
                        "Nullable(String)",
                        "Nullable(String)",
                        "Nullable(String)",
                        "Array(String)",
                        "Array(String)",
                        "Bool",
                        "Bool",
                        "Enum8('DIRECT'=1, 'CONDITIONAL'=2, 'CALL'=3, 'RETURN'=4, 'FALLTHROUGH'=5, 'UNKNOWN'=6)",
                        "Array(String)",
                        "Int8",
                        "DateTime64(3, 'UTC')",
                    ],
                },
                "function_analysis_errors": {
                    "table": "function_analysis_errors",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f["function_name"],
                            f["function_address"],
                            f["error_location"],
                            f.get(
                                "error_message", ""
                            ),  # it could be empty, how to handle it?
                            f.get("error_details", ""),
                            f.get("error_type", "unknown"),
                            md5(
                                f"{f['error_message']}{f['function_name']}{f['function_address']}{f['error_location']}".encode()
                            ).hexdigest(),
                            "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)",
                        "String",
                        "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