Xiao Ling

118 papers A* 12A 2B 6C 5Journal 71Unranked 21
YearRankTypeTitle / Venue / Authors
2026 J jnl
Displays
Yana Gao, Kang Yang, Tuo Zheng, Cong Peng, Xingyao Zhou, Xiao Ling, Xifeng Li, Jianhua Zhang
2025 J jnl
IEEE Trans. Geosci. Remote. Sens.
Chongjing Sun, Dongping Ming, Lu Xu, Shizhe Xie, Ran Liu, Xiao Ling
2025 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Yuejie Zhang, Qinghong Sheng, Kerui Li, Bo Wang, Jun Li, Xiao Ling, Fan Gao
2025 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Yuejie Zhang, Qinghong Sheng, Bo Wang, Jun Li, Xiao Ling, Zefeng Wu, Kerui Li, Qilong Wang, Fan Gao
2025 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Jianao Cai, Dongping Ming, Feng Liu, Xiao Ling, Ningjie Liu, Liang Zhang, Lu Xu, Yan Li, Mengyuan Zhu
2025 J jnl
J. Imaging Inform. Medicine
Tianyu Liu, Yurui Hu, Zehua Liu, Zeshuo Jiang, Xiao Ling, Xueling Zhu, Wenfei Li
2025 J jnl
Signal Image Video Process.
Xiang Liu, Mu Qiao, Bo Wang, Qinghong Sheng, Jun Li, Xiao Ling
2025 J jnl
Environ. Model. Softw.
Xiao Ling, Dongping Ming, Zhi Zhang, Jianao Cai, Wenyi Zhao, Mingzhi Zhang, Yongshuang Zhang, Bingbo Gao
2025 J jnl
CoRR
Xingyang He, Xiao Ling, Jie Liu
2025 J jnl
IEEE Trans. Geosci. Remote. Sens.
Xiao Ling, Dongping Ming, Wenhui Zhang, Jianao Cai, Liang Zhang, Lu Xu, Zhi Zhang
2024 J jnl
IEEE Trans. Geosci. Remote. Sens.
Jun Li, Chengjie Hu, Qinghong Sheng, Bo Wang, Xiao Ling, Fan Gao, Yunfei Xu, Zhiwei Li, Matthieu Molinier
2024 J jnl
IEEE Trans. Geosci. Remote. Sens.
Yang Du, Jun Li, Qinghong Sheng, Yuxin Zhu, Bo Wang, Xiao Ling
2024 conf
NLPCC (2)
Xiao Ling, Jialin Liu, Jindu Liu, Jianhua Wu, Jie Liu
2024 J jnl
Optim. Lett.
Xiao Ling, Anh Bui, Paul Brooks
2024 J jnl
CoRR
Ran Chen, Zeke Lian, Yueheng He, Xiao Ling, Fuyu Yang, Xueqi Yao, Xingjian Yi, Jing Zhao
2024 J jnl
CoRR
Derry Wijaya, Brendan Callahan, John Hewitt, Jie Gao, Xiao Ling, Marianna Apidianaki, Chris Callison-Burch
2024 J jnl
Pattern Recognit.
Zhaoxu Ding, Guoqiang Zhong, Xianping Qin, Qingyang Li, Zhenlin Fan, Zhaoyang Deng, Xiao Ling, Wei Xiang
2024 J jnl
IEEE Access
Xiao Ling, Tim Menzies, Christopher J. Hazard, Jack Shu, Jacob Beel
2024 J jnl
CoRR
Xiao Ling, Paul Brooks
2023 J jnl
IEEE Trans. Geosci. Remote. Sens.
Xiao Ling, Rongjun Qin
2023 J jnl
CoRR
Xiao Ling, Rongjun Qin
2023 conf
WWW (Companion Volume)
Xiao Ling, David Yan, Bilal Alsallakh, Ashutosh Pandey, Manan Bakshi, Pamela Bhattacharya
2023 J jnl
CoRR
Xiao Ling, Tim Menzies
2023 J jnl
Neurocomputing
Zhaoyang Niu, Guoqiang Zhong, Guohua Yue, Li-Na Wang, Hui Yu, Xiao Ling, Junyu Dong
2023 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Yangyang Chen, Dongping Ming, Junchuan Yu, Lu Xu, Yanni Ma, Yan Li, Xiao Ling, Yueqin Zhu
2023 J jnl
CoRR
Xiao Ling, Tim Menzies, Christopher J. Hazard, Jack Shu, Jacob Beel
2023 J jnl
Remote. Sens.
Hongjian Luo, Dongping Ming, Lu Xu, Xiao Ling
2023 J jnl
IEEE Trans. Software Eng.
Xiao Ling, Tim Menzies
2022 conf
CICAI (1)
Ming Guo, Shunfei Wang, Zhibo Wang, Ming Lu, Xiufen Cui, Xiao Ling, Feng Xu
2022 J jnl
CoRR
Xiao Ling, Rongjun Qin
2022 A* conf
ICSE
Zhuangbin Chen, Jinyang Liu, Yuxin Su, Hongyu Zhang, Xiao Ling, Michael R. Lyu
2022 J jnl
CoRR
Zhuangbin Chen, Jinyang Liu, Yuxin Su, Hongyu Zhang, Xiao Ling, Yongqiang Yang, Michael R. Lyu
2022 J jnl
IEEE Trans. Geosci. Remote. Sens.
Kui Zhang, Dongping Ming, Shigao Du, Lu Xu, Xiao Ling, Beichen Zeng, Xianwei Lv
2022 conf
EITCE
Qingxuan Du, Xiao Ling, Tiantian Jing, Yuankun Peng
2022 J jnl
Remote. Sens.
Xiao Ling, Yueqin Zhu, Dongping Ming, Yangyang Chen, Liang Zhang, Tongyao Du
2022 J jnl
IEEE Trans. Software Eng.
Xiao Ling, Rishabh Agrawal, Tim Menzies
2022 J jnl
Remote. Sens.
Rongjun Qin, Xiao Ling, Elisa Mariarosaria Farella, Fabio Remondino
2021 J jnl
CoRR
Rongjun Qin, Shuang Song, Xiao Ling, Mostafa M. El-Hashash
2021 conf
NLPCC (1)
Bingquan Wang, Jie Liu, Shaowei Chen, Xiao Ling, Shanpeng Wang, Wenzheng Zhang, Liyi Chen, Jiaxin Zhang
2021 J jnl
CoRR
Xiao Ling, Xu Huang, Rongjun Qin
2021 J jnl
CoRR
Ningli Xu, Debao Huang, Shuang Song, Xiao Ling, Chris Strasbaugh, Alper Yilmaz, Halil Sezen, Rongjun Qin
2021 J jnl
Int. J. Digit. Earth
Ningli Xu, Debao Huang, Shuang Song, Xiao Ling, Chris Strasbaugh, Alper Yilmaz, Halil Sezen, Rongjun Qin
2021 A* conf
ASE
Tianyi Yang, Jiacheng Shen, Yuxin Su, Xiao Ling, Yongqiang Yang, Michael R. Lyu
2021 J jnl
CoRR
Tianyi Yang, Jiacheng Shen, Yuxin Su, Xiao Ling, Yongqiang Yang, Michael R. Lyu
2021 A conf
CIDR
Laurel J. Orr, Megan Leszczynski, Neel Guha, Sen Wu, Simran Arora, Xiao Ling, Christopher Ré
2021 conf
EMNLP (Findings)
Maya Varma, Laurel J. Orr, Sen Wu, Megan Leszczynski, Xiao Ling, Christopher Ré
2021 J jnl
CoRR
Maya Varma, Laurel J. Orr, Sen Wu, Megan Leszczynski, Xiao Ling, Christopher Ré
2021 conf
ACL/IJCNLP (1)
Anthony Chen, Pallavi Gudipati, Shayne Longpre, Xiao Ling, Sameer Singh
2021 J jnl
CoRR
Anthony Chen, Pallavi Gudipati, Shayne Longpre, Xiao Ling, Sameer Singh
2021 J jnl
CoRR
Xiao Ling, Tim Menzies
2021 A* conf
ASE
Zhuangbin Chen, Jinyang Liu, Yuxin Su, Hongyu Zhang, Xuemin Wen, Xiao Ling, Yongqiang Yang, Michael R. Lyu
2021 J jnl
CoRR
Zhuangbin Chen, Jinyang Liu, Yuxin Su, Hongyu Zhang, Xuemin Wen, Xiao Ling, Yongqiang Yang, Michael R. Lyu
2021 A* conf
ICCV
Piaopiao Yu, Jie Guo, Fan Huang, Cheng Zhou, Hongwei Che, Xiao Ling, Yanwen Guo
2021 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Yangyang Chen, Dongping Ming, Xiao Ling, Xianwei Lv, Chenghu Zhou
2021 J jnl
CoRR
Laurel J. Orr, Atindriyo Sanyal, Xiao Ling, Karan Goel, Megan Leszczynski
2021 J jnl
Proc. VLDB Endow.
Laurel J. Orr, Atindriyo Sanyal, Xiao Ling, Karan Goel, Megan Leszczynski
2021 conf
IEEE BigData
Jianxin Sui, Xiao Ling, Xing Xiang, Genwei Zhang, Xiangchi Zhang
2020 J jnl
CoRR
Laurel J. Orr, Megan Leszczynski, Simran Arora, Sen Wu, Neel Guha, Xiao Ling, Christopher Ré
2020 conf
IEEE BigData
Yibo Chen, Xing Xiang, Xiao Ling, Xiangchi Zhang, Fan Wu, Jianliang Gao
2020 J jnl
CoRR
Xiao Ling, Rishabh Agrawal, Tim Menzies
2020 J jnl
Remote. Sens.
Sidan Yao, Xiao Ling, Fiona Nüesch, Gerhard Schrotter, Simon Schubiger, Zheng Fang, Long Ma, Zhen Tian
2020 J jnl
Remote. Sens.
Xiao Ling, Xu Huang, Yongjun Zhang, Gang Zhou
2020 J jnl
J. Intell. Manuf.
Jianfeng Tao, Chengjin Qin, Dengyu Xiao, Haotian Shi, Xiao Ling, Bingchu Li, Chengliang Liu
2020 J jnl
Remote. Sens.
Changlin Xiao, Rongjun Qin, Xiao Ling
2019 J jnl
IEEE Trans. Geosci. Remote. Sens.
Yongjun Zhang, Fei Wen, Zhi Gao, Xiao Ling
2019 J jnl
IEEE Geosci. Remote. Sens. Lett.
Yongjun Zhang, Xinyi Liu, Yi Zhang, Xiao Ling, Xu Huang
2019 J jnl
Robotics Auton. Syst.
Xiao Ling, Yuanshen Zhao, Liang Gong, Chengliang Liu, Tao Wang
2019 J jnl
Remote. Sens.
Lu Xu, Dongping Ming, Wen Zhou, Hanqing Bao, Yangyang Chen, Xiao Ling
2019 J jnl
WIREs Data Mining Knowl. Discov.
Guoqiang Zhong, Xiao Ling, Li-Na Wang
2019 conf
NAACL-HLT (2)
Boya Peng, Yejin Huh, Xiao Ling, Michele Banko
2019 J jnl
Remote. Sens.
Xinyi Liu, Yongjun Zhang, Xiao Ling, Yi Wan, Linyu Liu, Qian Li
2019 C conf
IGARSS
Changlin Xiao, Rongjun Qin, Xiao Ling, Hanning Yuan
2018 C conf
IGARSS
Xunwei Xie, Yongjun Zhang, Xiao Ling, Xiang Wang
2018 C conf
IGARSS
Xianzhang Zhu, Yongjun Zhang, Hui Cao, Kai Tan, Xiao Ling
2018 J jnl
IEEE Access
Yongjun Zhang, Xunwei Xie, Xiang Wang, Yansheng Li, Xiao Ling
2018 B conf
ICPR
Guoqiang Zhong, Yan Zheng, Xu-Yao Zhang, Hongxu Wei, Xiao Ling
2018 J jnl
IEEE Geosci. Remote. Sens. Lett.
Xianzhang Zhu, Hui Cao, Yongjun Zhang, Kai Tan, Xiao Ling
2018 C conf
IECON
Bingchu Li, Xiao Ling, Yixiang Huang, Liang Gong, Chengliang Liu
2018 J jnl
CoRR
Guoqiang Zhong, Guohua Yue, Xiao Ling
2018 J jnl
IEEE Geosci. Remote. Sens. Lett.
Fei Wen, Yongjun Zhang, Zhi Gao, Xiao Ling
2017 J jnl
IEEE Trans. Geosci. Remote. Sens.
Yansong Duan, Xiao Ling, Yongjun Zhang, Zuxun Zhang, Xinyi Liu, Kun Hu
2017 J jnl
Sensors
Bingchu Li, Xiao Ling, Yixiang Huang, Liang Gong, Chengliang Liu
2017 conf
GIoTS
Xiao Ling, Jie Sheng, Orlando Baiocchi, Xing Liu, Matthew E. Tolentino
2017 A* conf
EMNLP
Derry Wijaya, Brendan Callahan, John Hewitt, Jie Gao, Xiao Ling, Marianna Apidianaki, Chris Callison-Burch
2017 J jnl
Clust. Comput.
Bingchu Li, Xiao Ling, Yixiang Huang, Liang Gong, Chengliang Liu
2017 J jnl
IEEE Access
Xiao Ling, Bingchu Li, Liang Gong, Yixiang Huang, Chengliang Liu
2016 J jnl
Remote. Sens.
Xiao Ling, Yongjun Zhang, Jinxin Xiong, Xu Huang, Zhipeng Chen
2016 J jnl
IEEE Trans. Geosci. Remote. Sens.
Yongjun Zhang, Yi Wan, Xinhui Huang, Xiao Ling
2016 conf
HLT-NAACL
Angli Liu, Stephen Soderland, Jonathan Bragg, Christopher H. Lin, Xiao Ling, Daniel S. Weld
2016
Xiao Ling
2016 conf
HPCC/SmartCity/DSS
Xiao Ling, Jiahai Yang, Dan Wang, Jinfeng Chen, Liyao Li
2016 J jnl
J. Parallel Distributed Comput.
Xiao Ling, Yi Yuan, Dan Wang, Jiangchuan Liu, Jiahai Yang
2016 C conf
ISCC
Di Fu, Jiahai Yang, Xiao Ling, Hui Zhang
2016 conf
WF-IoT
Anindya Dey, Xiao Ling, Adnan Syed, Yuewen Zheng, Bob Landowski, David Anderson, Kim Stuart, Matthew E. Tolentino
2016 B conf
IWQoS
Xiao Ling, Yi Yuan, Dan Wang, Jiahai Yang
2016 conf
CCPR (1)
Guoqiang Zhong, Xiao Ling
2015 conf
HPCC/CSS/ICESS
Xiao Ling, Jiahai Yang, Dan Wang, Ye Wang
2015 J jnl
Trans. Assoc. Comput. Linguistics
Xiao Ling, Sameer Singh, Daniel S. Weld
2015 conf
ICIRA (1)
Xiao Ling, Liang Gong, Linlizi Wu, Bowen Wang, Binchu Li, Yixiang Huang, Chengliang Liu
2015 J jnl
IEEE Trans. Parallel Distributed Syst.
Xiao Ling, Shadi Ibrahim, Song Wu, Hai Jin
2015 conf
ICIRA (3)
Bin Zhou, Liang Gong, Qianli Chen, Yuanshen Zhao, Xiao Ling, Chengliang Liu
2014 conf
ROBIO
Diansheng Chen, Zhaoliang Peng, Xiao Ling
2014 J jnl
J. Comput.
Hou-de Su, Shu-rong Yu, Jian-ling Fan, Xiao Ling
2013 B conf
IM
Cong Xu, Jiahai Yang, Xiao Ling, Yuding Wang, Liyao Li
2013 B conf
MASCOTS
Xiao Ling, Shadi Ibrahim, Hai Jin, Song Wu, Songqiao Tao
2013 conf
AKBC@CIKM
Xiao Ling, Peter Clark, Daniel S. Weld
2013 J jnl
Future Gener. Comput. Syst.
Hai Jin, Xiao Ling, Shadi Ibrahim, Wenzhi Cao, Song Wu, Gabriel Antoniu
2013 A* conf
IJCAI
Xiao Ling, Alon Y. Halevy, Fei Wu, Cong Yu
2012 B conf
CCGRID
Xiao Ling, Hai Jin, Shadi Ibrahim, Wenzhi Cao, Song Wu
2012 A* conf
AAAI
Xiao Ling, Daniel S. Weld
2011 A* conf
ACL
Raphael Hoffmann, Congle Zhang, Xiao Ling, Luke Zettlemoyer, Daniel S. Weld
2010 A* conf
AAAI
Xiao Ling, Daniel S. Weld
2010 conf
FGIT-GDC/CA
Xiao Ling, Hai Jin, Song Wu, Xuanhua Shi
2008 A* conf
WWW
Xiao Ling, Gui-Rong Xue, Wenyuan Dai, Yun Jiang, Qiang Yang, Yong Yu
2008 B conf
DASFAA
Xiao Ling, Wenyuan Dai, Gui-Rong Xue, Yong Yu
2008 A* conf
KDD
Xiao Ling, Wenyuan Dai, Gui-Rong Xue, Qiang Yang, Yong Yu
2008 A conf
ICME
Xiao Ling, Jimin Jia, Nenghai Yu, Mingjing Li
2007 A* conf
WWW
Xiaochuan Ni, Gui-Rong Xue, Xiao Ling, Yong Yu, Qiang Yang
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