Xiangming Xiao

82 papers A* 1C 1Journal 78Unranked 2
YearRankTypeTitle / Venue / Authors
2026 J jnl
Environ. Model. Softw.
Hongfei Li, Jun Yang, Jiaxing Xin, Wenbo Yu, Jiayi Ren, Huisheng Yu, Xiangming Xiao, Jianhong (cecilia) Xia
2025 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Zhenjie Liu, Jialin Liu, Yingyue Su, Xiangming Xiao, Jingwei Dong, Luo Liu
2025 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Jiaxing Xin, Ying Cui, Jun Yang, Jiayi Ren, Wenbo Yu, Xiangming Xiao, Jianhong Cecilia Xia
2025 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Fang Liu, Xiangming Xiao, Yuanwei Qin, Luo Liu
2025 J jnl
Comput. Electron. Agric.
Sen Zhang, Nan Li, Yaoping Cui, Jinwei Dong, Le Yu, Lishan Ran, Ziyue Chen, Jiqiang Niu, Wei Yan, Kasturi Devi Kanniah, Xiangming Xiao
2024 conf
CHI Extended Abstracts
Qin Wu, Xiangming Xiao, Yugui Liu, Mark Billinghurst, Suranga Nanayakkara
2024 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Ling Yu, Lei Fan, Philippe Ciais, Jingfeng Xiao, Frédéric Frappart, Stephen Sitch, Jingming Chen, Xiangming Xiao, Rasmus Fensholt, Zhongbing Chang, Hongqian Fang, Xiaojun Li, Tiangxiang Cui, Mingguo Ma, Jean-Pierre Wigneron
2024 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Zhenjie Liu, Yingyue Su, Xiangming Xiao, Yuanwei Qin, Jun Li, Luo Liu
2024 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Duanrui Wang, Dehua Mao, Ming Wang, Xiangming Xiao, Chi-Yeung Choi, Chunlin Huang, Zongming Wang
2024 J jnl
Remote. Sens.
Jorge A. Celis, Xiangming Xiao, Paul M. White, Osvaldo M. R. Cabral, Helber C. Freitas
2024 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Qianmin Zhang, Jun Yang, Xinyue Ma, Jiaxing Xin, Jiayi Ren, Wenbo Yu, Xiangming Xiao, Jianhong Cecilia Xia
2024 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Jiayi Ren, Jun Yang, Wenbo Yu, Nan Cong, Xiangming Xiao, Jianhong Cecilia Xia, Xueming Li
2024 J jnl
Ecol. Informatics
Pradeep Wagle, Gopichandh Danala, Catherine Donner, Xiangming Xiao, Corey Moffet, Stacey A. Gunter, Wolfgang Jentner, David S. Ebert
2024 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Zhaoxuan Dong, Chunli Li, Cui Jin, Jiaxing Xin, Yuqing Zhang, Xiangming Xiao, Jianhong Cecilia Xia
2024 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Xinyue Ma, Jun Yang, Rui Zhang, Wenbo Yu, Jiayi Ren, Xiangming Xiao, Jianhong Cecilia Xia
2023 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Wenbo Yu, Jun Yang, Nan Cong, Jiayi Ren, Huisheng Yu, Xiangming Xiao, Jianhong Cecilia Xia
2023 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Ling Yu, Lei Fan, Philippe Ciais, Stephen Sitch, Rasmus Fensholt, Xiangming Xiao, Wenping Yuan, Jingming Chen, Yingtong Zhang, Xiaocui Wu, Yuanwei Qin, Mingguo Ma, Zhongbing Chang, Mengjia Wang, Kai Yan, Lisheng Song, Jean-Pierre Wigneron
2023 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Xi Zhang, Xiangming Xiao, Xinxin Wang, Xiao Xu, Shiyun Qiu, Lianghao Pan, Jun Ma, Ruiting Ju, Jihua Wu, Bo Li
2023 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Luo Liu, Shanggui Kang, Xiliu Xiong, Yuanwei Qin, Jie Wang, Zhenjie Liu, Xiangming Xiao
2023 J jnl
Comput. Environ. Urban Syst.
Fei He, Jun Yang, Yuqing Zhang, Wenbo Yu, Xiangming Xiao, Jianhong Cecilia Xia
2023 J jnl
Ecol. Informatics
Xinyue Ma, Jun Yang, Dongqi Sun, Rui Zhang, Xiangming Xiao, Jianhong Cecilia Xia
2023 A* conf
ICCV
Fudong Lin, Summer Crawford, Kaleb Guillot, Yihe Zhang, Yan Chen, Xu Yuan, Li Chen, Shelby Williams, Robert Minvielle, Xiangming Xiao, Drew Gholson, Nicolas Ashwell, Tri Setiyono, Brenda Tubana, Lu Peng, Magdy A. Bayoumi, Nian-Feng Tzeng
2023 J jnl
CoRR
Fudong Lin, Summer Crawford, Kaleb Guillot, Yihe Zhang, Yan Chen, Xu Yuan, Li Chen, Shelby Williams, Robert Minvielle, Xiangming Xiao, Drew Gholson, Nicolas Ashwell, Tri Setiyono, Brenda Tubana, Lu Peng, Magdy A. Bayoumi, Nian-Feng Tzeng
2023 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Chenchen Zhang, Xiangming Xiao, Liangcheng Zhao, Yuanwei Qin, Russell B. Doughty, Xin-Xin Wang, Jinwei Dong, Xuebin Yang
2023 J jnl
CoRR
Xiaoxin Zhang, Martin Brandt, Xiaoye Tong, Xiaowei Tong, Wenmin Zhang, Florian Reiner, Sizhuo Li, Feng Tian, Yuemin Yue, Weiqi Zhou, Bin Chen, Xiangming Xiao, Rasmus Fensholt
2022 J jnl
Remote. Sens.
Linghui Guo, Sha Zhao, Jiangbo Gao, Hebing Zhang, Youfeng Zou, Xiangming Xiao
2022 J jnl
Remote. Sens.
Han Xu, Xiangming Xiao, Yuanwei Qin, Zhi Qiao, Shaoqiu Long, Xianzhe Tang, Luo Liu
2022 J jnl
Remote. Sens.
Bangqian Chen, Ting Yun, Jun Ma, Weili Kou, Hailiang Li, Chuan Yang, Xiangming Xiao, Xian Zhang, Rui Sun, Guishui Xie, Zhixiang Wu
2022 J jnl
Remote. Sens.
Pradeep Wagle, Vijaya Gopal Kakani, Prasanna H. Gowda, Xiangming Xiao, Brian K. Northup, James P. S. Neel, Patrick J. Starks, Jean L. Steiner, Stacey A. Gunter
2022 J jnl
Remote. Sens.
Ruoqi Liu, Geli Zhang, Jinwei Dong, Yan Zhou, Nanshan You, Yingli He, Xiangming Xiao
2021 J jnl
Remote. Sens.
Enqin Liu, Xiangming Xiao, Huaiyong Shao, Xin Yang, Yali Zhang, Yang Yang
2021 J jnl
Remote. Sens.
Rajen Bajgain, Xiangming Xiao, Pradeep Wagle, John S. Kimball, Colin Brust, Jeffrey B. Basara, Prasanna Gowda, Patrick J. Starks, James P. S. Neel
2021 J jnl
Remote. Sens.
Han Li, Fu Xu, Zhichao Li, Nanshan You, Hui Zhou, Yan Zhou, Bangqian Chen, Yuanwei Qin, Xiangming Xiao, Jinwei Dong
2021 J jnl
Remote. Sens.
Jorge A. Celis, Hernan A. Moreno, Jeffrey B. Basara, Renee A. McPherson, Michael H. Cosh, Tyson E. Ochsner, Xiangming Xiao
2021 J jnl
Ecol. Informatics
Enqin Liu, Hui Zhao, Shuhui Zhang, Jing He, Xin Yang, Xiangming Xiao
2021 J jnl
Remote. Sens.
Zhiqi Yang, Jinwei Dong, Weili Kou, Yuanwei Qin, Xiangming Xiao
2021 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Xuebin Yang, Xiangming Xiao, Yuanwei Qin, Jie Wang, Kevin Neal
2021 J jnl
Remote. Sens.
Xiaocui Wu, Xiangming Xiao, Jean L. Steiner, Zhengwei Yang, Yuanwei Qin, Jie Wang
2020 J jnl
Remote. Sens.
Yang Hu, Xuelei Xu, Fayun Wu, Zhongqiu Sun, Haoming Xia, Qingmin Meng, Wenli Huang, Hua Zhou, Jinping Gao, Weitao Li, Daoli Peng, Xiangming Xiao
2020 J jnl
Remote. Sens.
Jean L. Steiner, Jeffrey Wetter, Shelby Robertson, Stephen Teet, Jie Wang, Xiaocui Wu, Yuting Zhou, David Brown, Xiangming Xiao
2020 J jnl
Remote. Sens.
Bangqian Chen, Tin Yun, Jun Ma, Weili Kou, Hailiang Li, Chuan Yang, Xiangming Xiao, Xian Zhang, Rui Sun, Guishui Xie, Zhixiang Wu
2020 J jnl
Ecol. Informatics
Yanyan Pei, Jinwei Dong, Yao Zhang, Jilin Yang, Yongqiang Zhang, Chongya Jiang, Xiangming Xiao
2020 J jnl
Multim. Tools Appl.
Yaqian Wu, Xiangming Xiao, Bangqian Chen, Jun Ma, Xinxin Wang, Yanan Zhang, Bin Zhao, Bo Li
2020 J jnl
Remote. Sens.
Fengfei Xin, Xiangming Xiao, Osvaldo M. R. Cabral, Paul M. White, Hai-Qiang Guo, Jun Ma, Bo Li, Bin Zhao
2019 J jnl
Remote. Sens.
Pei Wang, Xiaozheng Gan, Qingling Zhang, Guochao Bu, Li Li, Xiuxian Xu, Yaxin Li, Zichu Liu, Xiangming Xiao
2019 J jnl
Remote. Sens.
Yan Zhou, Jinwei Dong, Jiyuan Liu, Graciela Metternicht, Wei Shen, Nanshan You, Guosong Zhao, Xiangming Xiao
2019 J jnl
Remote. Sens.
Wen Zhuo, Jianxi Huang, Li Li, Xiaodong Zhang, Hongyuan Ma, Xinran Gao, Hai Huang, Baodong Xu, Xiangming Xiao
2019 J jnl
Remote. Sens.
Jia-Min Zong, Xin-Xin Wang, Qiao-Yan Zhong, Xiangming Xiao, Jun Ma, Bin Zhao
2019 J jnl
Remote. Sens.
Yingbing Wang, Jun Ma, Xiangming Xiao, Xinxin Wang, Shengqi Dai, Bin Zhao
2019 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Chun-Ying Ren, Zongming Wang, Yuanzhi Zhang, Bai Zhang, Lin Chen, Yanbiao Xi, Xiangming Xiao, Russell B. Doughty, Mingyue Liu, Mingming Jia, Dehua Mao, Kaishan Song
2019 J jnl
Remote. Sens.
Hui Zhou, Fu Xu, Jinwei Dong, Zhiqi Yang, Guosong Zhao, Jun Zhai, Yuanwei Qin, Xiangming Xiao
2019 J jnl
Remote. Sens.
Linghui Guo, Jiangbo Gao, Chengyuan Hao, Linlin Zhang, Shaohong Wu, Xiangming Xiao
2018 J jnl
Remote. Sens.
Deli Zhai, Jinwei Dong, Georg Cadisch, Mingcheng Wang, Weili Kou, Jianchu Xu, Xiangming Xiao, Sawaid Abbas
2018 J jnl
Sensors
Xi Yang, Hanyu Shi, Atticus E. L. Stovall, Kaiyu Guan, Guofang Miao, Yongguang Zhang, Yao Zhang, Xiangming Xiao, Youngryel Ryu, Jung-Eun Lee
2018 J jnl
Remote. Sens.
Bangqian Chen, Xiangming Xiao, Zhixiang Wu, Tin Yun, Weili Kou, Huichun Ye, Qinghuo Lin, Russell B. Doughty, Jinwei Dong, Jun Ma, Wei Luo, Guishui Xie, Jianhua Cao
2018 J jnl
Remote. Sens.
Zhiqi Yang, Jinwei Dong, Yuanwei Qin, Wenjian Ni, Guosong Zhao, Wei Chen, Bangqian Chen, Weili Kou, Jie Wang, Xiangming Xiao
2018 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Bangqian Chen, Xiangming Xiao, Huichun Ye, Jun Ma, Russell B. Doughty, Xiangping Li, Bin Zhao, Zhixiang Wu, Rui Sun, Jinwei Dong, Yuanwei Qin, Guishui Xie
2018 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Weiheng Xu, Yuanwei Qin, Xiangming Xiao, Guangzhi Di, Russell B. Doughty, Yuting Zhou, Zhenhua Zou, Lei Kong, Quanfu Niu, Weili Kou
2018 J jnl
PLoS Comput. Biol.
Edward M. Hill, Thomas A. House, Madhur S. Dhingra, Wantanee Kalpravidh, Subhash Morzaria, Muzaffar G. Osmani, Eric Brum, Mat Yamage, Md. A. Kalam, Diann J. Prosser, John Y. Takekawa, Xiangming Xiao, Marius Gilbert, Michael J. Tildesley
2018 J jnl
Remote. Sens.
Xiaoyan Zhu, Yanyan Pei, Zhaopei Zheng, Jinwei Dong, Yao Zhang, Junbang Wang, Lajiao Chen, Russell B. Doughty, Geli Zhang, Xiangming Xiao
2017 J jnl
ISPRS Int. J. Geo Inf.
Zhiqi Yang, Jinwei Dong, Jiyuan Liu, Jun Zhai, Wenhui Kuang, Guosong Zhao, Wei Shen, Yan Zhou, Yuanwei Qin, Xiangming Xiao
2017 J jnl
Environ. Model. Softw.
Jun Ma, Xiangming Xiao, Rencang Bu, Russell B. Doughty, Yuanman Hu, Bangqian Chen, Xiangping Li, Bin Zhao
2017 J jnl
Environ. Model. Softw.
Guang Xu, Xuan Zhu, Dongjie Fu, Jinwei Dong, Xiangming Xiao
2017 J jnl
Remote. Sens.
Guosong Zhao, Jinwei Dong, Jiyuan Liu, Jun Zhai, Yaoping Cui, Tian He, Xiangming Xiao
2016 J jnl
Int. J. Geogr. Inf. Sci.
Yuwei Wang, Ze Luo, John Y. Takekawa, Diann J. Prosser, Yan Xiong, Scott H. Newman, Xiangming Xiao, Nyambayar Batbayar, Kyle Spragens, Sivananinthaperumal Balachandran, Baoping Yan
2016 J jnl
Remote. Sens.
Rong Zhang, Zutao Ouyang, Xiao Xie, Hai-Qiang Guo, Dun-Yan Tan, Xiangming Xiao, Jiaguo Qi, Bin Zhao
2016 J jnl
Remote. Sens.
Yuanwei Qin, Xiangming Xiao, Jie Wang, Jinwei Dong, Kayti Ewing, Bruce Hoagland, Daniel J. Hough, Todd D. Fagin, Zhenhua Zou, George L. Geissler, George Z. Xian, Thomas R. Loveland
2016 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Yuting Zhou, Xiangming Xiao, Yuanwei Qin, Jinwei Dong, Geli Zhang, Weili Kou, Cui Jin, Jie Wang, Xiangping Li
2016 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Bangqian Chen, Xiangping Li, Xiangming Xiao, Bin Zhao, Jinwei Dong, Weili Kou, Yuanwei Qin, Chuan Yang, Zhixiang Wu, Rui Sun, Guoyu Lan, Guishui Xie
2016 J jnl
Int. J. Geogr. Inf. Sci.
Diann J. Prosser, Eric C. Palm, John Y. Takekawa, Delong Zhao, Xiangming Xiao, Peng Li, Ying Liu, Scott H. Newman
2016 J jnl
Remote. Sens.
Xiaoming Kang, Yanbin Hao, Xiaoyong Cui, Huai Chen, Sanxiang Huang, Yangong Du, Wei Li, Paul Kardol, Xiangming Xiao, Lijuan Cui
2015 J jnl
Remote. Sens.
Weili Kou, Xiangming Xiao, Jinwei Dong, Shu Gan, Deli Zhai, Geli Zhang, Yuanwei Qin, Li Li
2015 J jnl
Remote. Sens.
Li Li, Jinwei Dong, Simon Njeudeng Tenku, Xiangming Xiao
2014 J jnl
Remote. Sens.
Junbang Wang, Jinwei Dong, Jiyuan Liu, Mei Huang, Guicai Li, Steven W. Running, William Kolby Smith, Warwick Harris, Nobuko Saigusa, Hiroaki Kondo, Yunfen Liu, Takashi Hirano, Xiangming Xiao
2011 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Nathan Torbick, William A. Salas, Stephen Hagen, Xiangming Xiao
2010 conf
Geoinformatics
Yun Zhang, Zhigang Liu, Yong Zhang, Hua Yang, Yanchen Bo, Liqun Fang, Xiangming Xiao
2009 J jnl
Remote. Sens.
Xiangming Xiao, Chandrashekhar M. Biradar, Christina Czarnecki, Tunrayo Alabi, Michael Keller
2009 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Chandrashekhar M. Biradar, Prasad S. Thenkabail, Praveen Noojipady, Yuanjie Li, Venkateswarlu Dheeravath, Hugh Turral, Naga Manohar Velpuri, Murali K. Gumma, Obi Reddy P. Gangalakunta, Xueliang L. Cai, Xiangming Xiao, Mitchell Schull, Ranjith D. Alankara, Sarath Gunasinghe, Sadir Mohideen
2007 J jnl
Ann. GIS
Huiyong Sang, Hui Lin, Limin Yang, Ying Liu, Xiangming Xiao
2006 J jnl
IEEE Trans. Geosci. Remote. Sens.
Xiangming Xiao
1993 C conf
ISCAS
Xiangming Xiao, Robert Spence
1992 J jnl
Int. J. Circuit Theory Appl.
Xiangming Xiao, Robert Spence
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