Jaime Teevan

150 papers A* 55A 27B 6C 1Journal 29Unranked 26
YearRankTypeTitle / Venue / Authors
2024 conf
CHI Extended Abstracts
Jofish Kaye, Jaime Teevan, Victoria Bellotti, Lauren Wilcox
2024 conf
ACL (1)
Ying-Chun Lin, Jennifer Neville, Jack W. Stokes, Longqi Yang, Tara Safavi, Mengting Wan, Scott Counts, Siddharth Suri, Reid Andersen, Xiaofeng Xu, Deepak Gupta, Sujay Kumar Jauhar, Xia Song, Georg Buscher, Saurabh Tiwary, Brent J. Hecht, Jaime Teevan
2024 J jnl
CoRR
Ying-Chun Lin, Jennifer Neville, Jack W. Stokes, Longqi Yang, Tara Safavi, Mengting Wan, Scott Counts, Siddharth Suri, Reid Andersen, Xiaofeng Xu, Deepak Gupta, Sujay Kumar Jauhar, Xia Song, Georg Buscher, Saurabh Tiwary, Brent J. Hecht, Jaime Teevan
2023 J jnl
AI Matters
Jing Ma, Mengting Wan, Longqi Yang, Jundong Li, Brent J. Hecht, Jaime Teevan
2023 J jnl
SIGIR Forum
Jaime Teevan
2023 A* conf
IJCAI
Jing Ma, Mengting Wan, Longqi Yang, Jundong Li, Brent J. Hecht, Jaime Teevan
2023 J jnl
Trans. Recomm. Syst.
Kiran Tomlinson, Mengting Wan, Cao Lu, Brent J. Hecht, Jaime Teevan, Longqi Yang
2022 A* conf
CHI
Harmanpreet Kaur, Daniel McDuff, Alex C. Williams, Jaime Teevan, Shamsi T. Iqbal
2022 A conf
CIKM
Jaime Teevan
2022 A* conf
WWW
Jaime Teevan
2022 A* conf
KDD
Jing Ma, Mengting Wan, Longqi Yang, Jundong Li, Brent J. Hecht, Jaime Teevan
2022 J jnl
CoRR
Jing Ma, Mengting Wan, Longqi Yang, Jundong Li, Brent J. Hecht, Jaime Teevan
2022 A* conf
SIGIR
Jaime Teevan
2021 A* conf
CHI
Hancheng Cao, Chia-Jung Lee, Shamsi T. Iqbal, Mary Czerwinski, Priscilla N. Y. Wong, Sean Rintel, Brent J. Hecht, Jaime Teevan, Longqi Yang
2021 J jnl
CoRR
Hancheng Cao, Chia-Jung Lee, Shamsi T. Iqbal, Mary Czerwinski, Priscilla N. Y. Wong, Sean Rintel, Brent J. Hecht, Jaime Teevan, Longqi Yang
2021 A conf
RecSys
Jyun-Yu Jiang, Chia-Jung Lee, Longqi Yang, Bahareh Sarrafzadeh, Brent J. Hecht, Jaime Teevan
2021 J jnl
CoRR
Jyun-Yu Jiang, Chia-Jung Lee, Longqi Yang, Bahareh Sarrafzadeh, Brent J. Hecht, Jaime Teevan
2021 A* conf
CHI
Amanda Swearngin, Shamsi T. Iqbal, Victor Poznanski, Mark J. Encarnación, Paul N. Bennett, Jaime Teevan
2020 J jnl
CoRR
Longqi Yang, Sonia Jaffe, David Holtz, Siddharth Suri, Shilpi Sinha, Jeffrey Weston, Connor Joyce, Neha Shah, Kevin Sherman, Chia-Jung Lee, Brent J. Hecht, Jaime Teevan
2020 A* conf
CHI
Harmanpreet Kaur, Alex C. Williams, Daniel McDuff, Mary Czerwinski, Jaime Teevan, Shamsi T. Iqbal
2020 A* conf
UIST
Michael S. Bernstein, Irene Greif, Wendy E. Mackay, Hiroshi Ishii, Jonathan Grudin, Karrie Karahalios, Meredith Ringel Morris, Aniket Kittur, Jaime Teevan, Amy X. Zhang, Niloufar Salehi
2019 A* conf
CHI
Nikolas Martelaro, Jaime Teevan, Shamsi T. Iqbal
2019 A conf
WSDM
Jaime Teevan
2019 A* conf
CHI
Nathan Hahn, Shamsi T. Iqbal, Jaime Teevan
2019 A* conf
CHI
Saleema Amershi, Daniel S. Weld, Mihaela Vorvoreanu, Adam Fourney, Besmira Nushi, Penny Collisson, Jina Suh, Shamsi T. Iqbal, Paul N. Bennett, Kori Inkpen, Jaime Teevan, Ruth Kikin-Gil, Eric Horvitz
2019 A* conf
UIST
Alex C. Williams, Harmanpreet Kaur, Shamsi T. Iqbal, Ryen W. White, Jaime Teevan, Adam Fourney
2019 A* conf
CHI
Qian Yang, Justin Cranshaw, Saleema Amershi, Shamsi T. Iqbal, Jaime Teevan
2018 J jnl
Proc. ACM Hum. Comput. Interact.
Harmanpreet Kaur, Alex C. Williams, Anne Loomis Thompson, Walter S. Lasecki, Shamsi T. Iqbal, Jaime Teevan
2018 A* conf
UIST
Shamsi T. Iqbal, Jaime Teevan, Daniel J. Liebling, Anne Loomis Thompson
2018 conf
CHI Extended Abstracts
Rhema Linder, Shamsi T. Iqbal, Jaime Teevan
2018 A* conf
CHI
Alex C. Williams, Harmanpreet Kaur, Gloria Mark, Anne Loomis Thompson, Shamsi T. Iqbal, Jaime Teevan
2018 A* conf
UIST
Jaime Teevan
2018 conf
CHI Extended Abstracts
Harmanpreet Kaur, Alex C. Williams, Anne Loomis Thompson, Walter S. Lasecki, Shamsi T. Iqbal, Jaime Teevan
2017 B conf
Creativity & Cognition
Jaime Teevan, Lisa Yu
2017 A* conf
CHI
Justin Cranshaw, Emad Elwany, Todd Newman, Rafal Kocielnik, Bowen Yu, Sandeep Soni, Jaime Teevan, Andrés Monroy-Hernández
2017 J jnl
CoRR
Justin Cranshaw, Emad Elwany, Todd Newman, Rafal Kocielnik, Bowen Yu, Sandeep Soni, Jaime Teevan, Andrés Monroy-Hernández
2017 A conf
CSCW
Niloufar Salehi, Jaime Teevan, Shamsi T. Iqbal, Ece Kamar
2017 B conf
HCOMP
Harmanpreet Kaur, Mitchell L. Gordon, Yiwei Yang, Jeffrey P. Bigham, Jaime Teevan, Ece Kamar, Walter S. Lasecki
2017 J jnl
J. Assoc. Inf. Sci. Technol.
Mona Haraty, Zhongyuan Wang, Helen J. Wang, Shamsi T. Iqbal, Jaime Teevan
2017 J jnl
SIGIR Forum
Jaime Teevan, Susan T. Dumais, Eric Horvitz
2016 A* conf
CHI
Carrie J. Cai, Shamsi T. Iqbal, Jaime Teevan
2016 A* conf
SIGIR
Jin Young Kim, Jaime Teevan, Nick Craswell
2016 conf
CHI Extended Abstracts
William Jones, Victoria Bellotti, Robert G. Capra, Jesse David Dinneen, Gloria Mark, Catherine C. Marshall, Karyn Moffatt, Jaime Teevan, Maximus Van Kleek
2016 B ed.
CHIIR
Diane Kelly, Robert Capra, Nicholas J. Belkin, Jaime Teevan, Pertti Vakkari
2016 conf
CHI Extended Abstracts
Jaime Teevan, Shamsi T. Iqbal, Carrie J. Cai, Jeffrey P. Bigham, Michael S. Bernstein, Elizabeth M. Gerber
2016 A* conf
CHI
Jaime Teevan, Shamsi T. Iqbal, Curtis von Veh
2016 conf
CHI Extended Abstracts
Danaë Metaxa-Kakavouli, Gili Rusak, Jaime Teevan, Michael S. Bernstein
2016 J jnl
XRDS
Jaime Teevan
2016 J jnl
ACM Trans. Intell. Syst. Technol.
Yubin Kim, Kevyn Collins-Thompson, Jaime Teevan
2016 A* conf
CHI
Michael Nebeling, Alexandra To, Anhong Guo, Adrian A. de Freitas, Jaime Teevan, Steven P. Dow, Jeffrey P. Bigham
2015 A* conf
CHI
William Jones, Robert Capra, Anne Diekema, Jaime Teevan, Manuel A. Pérez-Quiñones, Jesse David Dinneen, Bradley M. Hemminger
2015 A* conf
CHI
Justin Cheng, Jaime Teevan, Shamsi T. Iqbal, Michael S. Bernstein
2015 B conf
HCOMP
Elena Agapie, Jaime Teevan, Andrés Monroy-Hernández
2015 conf
CHI Extended Abstracts
Daniel M. Russell, Jaime Teevan, Meredith Ringel Morris, Marti A. Hearst, Ed H. Chi
2015 A* conf
IJCAI
Peter Organisciak, Jaime Teevan, Susan T. Dumais, Robert C. Miller, Adam Tauman Kalai
2015 A* conf
CHI
Justin Cheng, Jaime Teevan, Michael S. Bernstein
2015 C conf
ICCC
Miaomiao Wen, Nancy Baym, Omer Tamuz, Jaime Teevan, Susan T. Dumais, Adam Kalai
2015 A conf
CIKM
Jaime Teevan
2015 A conf
HotOS
Helen J. Wang, Alexander Moshchuk, Michael Gamon, Shamsi T. Iqbal, Eli T. Brown, Ashish Kapoor, Christopher Meek, Eric Yawei Chen, Yuan Tian, Jaime Teevan, Mary Czerwinski, Susan T. Dumais
2015 J jnl
CoRR
Michael Nebeling, Anhong Guo, Kyle I. Murray, Annika Tostengard, Angelos Giannopoulos, Martin Mihajlov, Steven Dow, Jaime Teevan, Jeffrey P. Bigham
2015 conf
UIST (Adjunct Volume)
Michael Nebeling, Anhong Guo, Alexandra To, Steven Dow, Jaime Teevan, Jeffrey P. Bigham
2014 B conf
HCOMP
Peter Organisciak, Jaime Teevan, Susan T. Dumais, Robert C. Miller, Adam Tauman Kalai
2014 A* conf
SIGIR
Chia-Jung Lee, Jaime Teevan, Sebastian de la Chica
2014 A* conf
SIGIR
Diane Kelly, Filip Radlinski, Jaime Teevan
2014 A* conf
SIGIR
Diane Kelly, Filip Radlinski, Jaime Teevan
2014 A* conf
SIGIR
Avishay Livne, Vivek Gokuladas, Jaime Teevan, Susan T. Dumais, Eytan Adar
2014 A conf
CSCW
Walter S. Lasecki, Jaime Teevan, Ece Kamar
2014 A conf
WSDM
Carsten Eickhoff, Jaime Teevan, Ryen White, Susan T. Dumais
2014 conf
CHI Extended Abstracts
Jaime Teevan, Daniel J. Liebling, Walter S. Lasecki
2014 J jnl
Commun. ACM
Jaime Teevan, Kevyn Collins-Thompson, Ryen W. White, Susan T. Dumais
2014 J jnl
Computer
Jaime Teevan, Meredith Ringel Morris, Shiri Azenkot
2014 A conf
CSCW
Anne Oeldorf-Hirsch, Brent J. Hecht, Meredith Ringel Morris, Jaime Teevan, Darren Gergle
2014 ch.
Ways of Knowing in HCI
Susan T. Dumais, Robin Jeffries, Daniel M. Russell, Diane Tang, Jaime Teevan
2014 conf
CSCW Companion
Jaime Teevan, Meredith Ringel Morris, Shiri Azenkot
2013 A conf
WSDM
Matthias Böhmer, Ernesto William De Luca, Alan Said, Jaime Teevan
2013 A conf
ICWSM
Jin-Woo Jeong, Meredith Ringel Morris, Jaime Teevan, Daniel J. Liebling
2013 J jnl
ACM Trans. Inf. Syst.
Kira Radinsky, Krysta M. Svore, Susan T. Dumais, Milad Shokouhi, Jaime Teevan, Alex Bocharov, Eric Horvitz
2013 A* conf
CHI
Eytan Adar, Desney S. Tan, Jaime Teevan
2013 conf
CHI Extended Abstracts
Makoto P. Kato, Ryen W. White, Jaime Teevan, Susan T. Dumais
2013 conf
TREC
Yubin Kim, Kevyn Collins-Thompson, Jaime Teevan
2013 conf
HCOMP (Works in Progress / Demos)
Peter Organisciak, Jaime Teevan, Susan T. Dumais, Robert C. Miller, Adam Tauman Kalai
2013 ed.
CaRR@WSDM
Matthias Böhmer, Ernesto William De Luca, Alan Said, Jaime Teevan
2013 conf
HCIR
Jaime Teevan, Kevyn Collins-Thompson, Ryen W. White, Susan T. Dumais, Yubin Kim
2013 conf
Mobile HCI
Matthias Böhmer, T. Scott Saponas, Jaime Teevan
2013 conf
CSCW Companion
Mark S. Ackerman, Lada A. Adamic, Nicole B. Ellison, Darren Gergle, Brent J. Hecht, Cliff Lampe, Meredith Ringel Morris, Jaime Teevan
2013 A conf
ICWSM
Sanjay Ram Kairam, Meredith Ringel Morris, Jaime Teevan, Daniel J. Liebling, Susan T. Dumais
2013 A conf
CIKM
Jin Young Kim, Mark Cramer, Jaime Teevan, Dmitry Lagun
2013 A conf
CSCW
Jaime Teevan, Alexander Hehmeyer
2012 A* conf
SIGIR
Krysta M. Svore, Jaime Teevan, Susan T. Dumais, Anagha Kulkarni
2012 A* conf
CHI
Michael S. Bernstein, Jaime Teevan, Susan T. Dumais, Daniel J. Liebling, Eric Horvitz
2012 conf
Mobile HCI
Jaime Teevan, Daniel J. Liebling, Ann Paradiso, Carlos Garcia Jurado Suarez, Curtis von Veh, Darren Gehring
2012 A* conf
WWW
Kira Radinsky, Krysta M. Svore, Susan T. Dumais, Jaime Teevan, Alex Bocharov, Eric Horvitz
2012 conf
CSCW (Companion)
Robert Capra, Jaime Teevan
2012 A ed.
WSDM
Eytan Adar, Jaime Teevan, Eugene Agichtein, Yoelle Maarek
2012 A conf
ICWSM
Brent J. Hecht, Jaime Teevan, Meredith Ringel Morris, Daniel J. Liebling
2012 J jnl
SIGWEB Newsl.
Eytan Adar, Jaime Teevan
2012 A* conf
CHI
Scott Bateman, Jaime Teevan, Ryen W. White
2012 A* conf
CHI
Shahriyar Amini, A. J. Bernheim Brush, John Krumm, Jaime Teevan, Amy K. Karlson
2012 conf
Mobile HCI (Companion)
Karen Church, Jaime Teevan, Matt Jones
2011 A conf
WSDM
Jaime Teevan, Daniel Ramage, Meredith Ringel Morris
2011 A* conf
WWW
Lydia B. Chilton, Jaime Teevan
2011 A conf
ICWSM
Jiang Yang, Meredith Ringel Morris, Jaime Teevan, Lada A. Adamic, Mark S. Ackerman
2011 A conf
ICWSM
Jaime Teevan, Meredith Ringel Morris, Katrina Panovich
2011 A* conf
SIGIR
Alexander Kotov, Paul N. Bennett, Ryen W. White, Susan T. Dumais, Jaime Teevan
2011 A conf
WSDM
Jaime Teevan, Daniel J. Liebling, Gayathri Ravichandran Geetha
2011 A conf
WSDM
Anagha Kulkarni, Jaime Teevan, Krysta M. Svore, Susan T. Dumais
2011 conf
Mobile HCI
Jaime Teevan, Amy K. Karlson, Shahriyar Amini, A. J. Bernheim Brush, John Krumm
2011 ch.
Interactive Information Seeking, Behaviour and Retrieval
Jaime Teevan, Susan T. Dumais
2010 A conf
ICWSM
Meredith Ringel Morris, Jaime Teevan, Katrina Panovich
2010 A* conf
CHI
Jaime Teevan, Susan T. Dumais, Daniel J. Liebling
2010 A conf
WSDM
Sarah K. Tyler, Jaime Teevan
2010 J jnl
ACM Trans. Comput. Hum. Interact.
Jaime Teevan, Susan T. Dumais, Eric Horvitz
2010 A* conf
CHI
Meredith Ringel Morris, Jaime Teevan, Katrina Panovich
2010 J jnl
SIGIR Forum
David Elsweiler, Gareth J. F. Jones, Liadh Kelly, Jaime Teevan
2009 A* conf
UIST
Jaime Teevan, Susan T. Dumais, Daniel J. Liebling, Richard L. Hughes
2009 A conf
WSDM
Ryen W. White, Susan T. Dumais, Jaime Teevan
2009 book
Collaborative Web Search
Meredith Ringel Morris, Jaime Teevan
2009 A conf
WSDM
Jaime Teevan, Meredith Ringel Morris, Steve Bush
2009 B conf
Creativity & Cognition
Paul André, m. c. schraefel, Jaime Teevan, Susan T. Dumais
2009 A* conf
CHI
Paul André, Jaime Teevan, Susan T. Dumais
2009 ed.
UIIR@SIGIR
Nicholas J. Belkin, Ralf Bierig, Georg Buscher, Ludger van Elst, Jacek Gwizdka, Joemon M. Jose, Jaime Teevan
2009 A* conf
CHI
Eytan Adar, Jaime Teevan, Susan T. Dumais
2009 J jnl
SIGIR Forum
Georg Buscher, Jacek Gwizdka, Jaime Teevan, Nicholas J. Belkin, Ralf Bierig, Ludger van Elst, Joemon M. Jose
2009 conf
ASIST
Deborah Barreau, Jaime Teevan
2009 A conf
WSDM
Eytan Adar, Jaime Teevan, Susan T. Dumais, Jonathan L. Elsas
2009 J jnl
CoRR
Meredith Ringel Morris, Jaime Teevan
2009 A* conf
CHI
Jaime Teevan, Edward Cutrell, Danyel Fisher, Steven Mark Drucker, Gonzalo A. Ramos, Paul André, Chang Hu
2008 A conf
CSCW
Meredith Ringel Morris, Jaime Teevan, Steve Bush
2008 A* conf
SIGIR
Ryen W. White, Susan T. Dumais, Jaime Teevan
2008 J jnl
ACM Trans. Inf. Syst.
Jaime Teevan
2008 A* conf
CHI
Eytan Adar, Jaime Teevan, Susan T. Dumais
2008 J jnl
SIGIR Forum
Jaime Teevan, William Jones, Robert Capra
2008 conf
CHI Extended Abstracts
Jaime Teevan, William Jones
2008 A* conf
SIGIR
Jaime Teevan, Susan T. Dumais, Daniel J. Liebling
2007 conf
ASIST
Jaime Teevan
2007 A* conf
SIGIR
Jaime Teevan, Susan T. Dumais, Eric Horvitz
2007 A* conf
SIGIR
Jaime Teevan, Eytan Adar, Rosie Jones, Michael A. S. Potts
2007 J jnl
SIGIR Forum
G. Craig Murray, Jaime Teevan
2007
Jaime Teevan
2007 A* conf
UIST
Jaime Teevan
2006 A* conf
SIGIR
Jaime Teevan, Eytan Adar, Rosie Jones, Michael A. S. Potts
2006 conf
CHI Extended Abstracts
Jaime Teevan
2006 J jnl
Commun. ACM
Jaime Teevan, William Jones, Benjamin B. Bederson
2006 J jnl
Commun. ACM
Edward Cutrell, Susan T. Dumais, Jaime Teevan
2005 A* conf
SIGIR
Jaime Teevan, Susan T. Dumais, Eric Horvitz
2004 A* conf
CHI
Jaime Teevan, Christine Alvarado, Mark S. Ackerman, David R. Karger
2003 A* conf
SIGIR
Jaime Teevan, David R. Karger
2003 J jnl
SIGIR Forum
Diane Kelly, Jaime Teevan
2003 A* conf
ICML
Jason D. M. Rennie, Lawrence Shih, Jaime Teevan, David R. Karger
2001 conf
CHI Extended Abstracts
Jaime Teevan
redb/extractors/decompiler/DecompileBinja.py
← Index redb/extractors/decompiler/DecompileBinja.py python
import hashlib
import inspect
import json
import logging
import os
import signal
import time
from datetime import datetime, timezone
from typing import Dict, Any, Optional
from pathlib import Path
import subprocess
import sys

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

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

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

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

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

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

    def __enter__(self):
        return self

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

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

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

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

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

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

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

                return False

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

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

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

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

                return False

            return False

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

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

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

            # Force garbage collection
            import gc

            gc.collect()

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

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

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


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

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

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

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

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

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

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

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

        finally:
            self.cleanup_run()

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

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

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

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

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

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

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

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

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

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

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

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

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


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

            export = {"multi_table": True}

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

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

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


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

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

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

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

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

            return export

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

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


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

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

    # Parse command line arguments
    import argparse

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

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