Mansoor Ahmed

71 papers A* 1B 3C 5Misc 3Journal 41Unranked 16
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Mansoor Ahmed, Nadeem Taj, Imdad Ullah Khan, Hemanth Venkateswara, Murray Patterson
2025 J jnl
IEEE CAA J. Autom. Sinica
Mansoor Ahmed, Ruben Costa, Rui Branco, Jorge Calado, José Ferreira, Filippo Emanuele Ciarapica, Francisco Fraile, Mohamed Lamine Mekhalfi
2025 J jnl
PeerJ Comput. Sci.
Nadeem Yaqub, Jianbiao Zhang, Muhammad Irfan Khalid, Weiru Wang, Markus Helfert, Mansoor Ahmed, Jungsuk Kim
2025 conf
ICCABS
Mansoor Ahmed, Sarwan Ali, Avais Jan, Imdad Ullah Khan, Murray Patterson
2025 conf
PoEM Companion
Azra Aryania, Mansoor Ahmed, Markus Helfert
2024 J jnl
PeerJ Comput. Sci.
Kainat Ansar, Mansoor Ahmed, Saif Ur Rehman Malik, Markus Helfert, Jungsuk Kim
2024 B conf
ARES
Ibtisam Ehsan, Muhammad Irfan Khalid, Markus Helfert, Mansoor Ahmed
2024 ed.
PoEM Companion
Simon Hacks, Ben Roelens, Marite Kirikova, Iris Reinhartz-Berger, Dominik Bork, John Krogstie, Geert Poels, Jonas Van Riel, Philipp Zech, Michael Vierhauser, Ruth Breu, Hans Vangheluwe, Kurt Sandkuhl, Souvik Barat, Vinay Kulkarni, Markus Helfert, Mansoor Ahmed, Shahid Hussain
2024 conf
PoEM Companion
Mansoor Ahmed, Claudia Roessing, Priyanka Singh, Gabriel Hogan, Markus Helfert
2024 conf
PoEM Companion
Ibtisam Ehsan, Muhammad Irfan Khalid, Markus Helfert, Nadeem Yaqub, Mansoor Ahmed
2024 conf
I-ESA Workshops
Mansoor Ahmed, Ruben Costa, Rui Branco, José Ferreira, Francisco Fraile, Filippo Emanuele Ciarapica
2024 J jnl
Multim. Tools Appl.
Saira Beg, Adeel Anjum, Mansoor Ahmed
2023 J jnl
Comput. Syst. Sci. Eng.
Chaudhary Hassan Abbas Gondal, Muhammad Irfan, Sarmad Shafique, Muhammad Salman Bashir, Mansoor Ahmed, Osama Mohammed Alshehri, Hassan H. Almasoudi, Samar M. Alqhtani, Mohammed M. Jalal, Malik A. Altayar, Khalaf F. Alsharif
2023 conf
ISC2
Muhammad Irfan Khalid, Mansoor Ahmed
2023 J jnl
Sensors
Mansoor Ahmed, Amil Rohani Dar, Markus Helfert, Abid Khan, Jungsuk Kim
2023 J jnl
Sensors
Muhammad Irfan Khalid, Mansoor Ahmed, Jungsuk Kim
2023 conf
ICE/ITMC
Negin Mehrbod, Ruben Costa, Ahmad Mehrbod, Mansoor Ahmed, Fenareti Lampathaki
2023 conf
ICCCI (CCIS Volume)
Mansoor Ahmed, Usama Sardar, Sarwan Ali, Shafiq Alam, Murray Patterson, Imdad Ullah Khan
2023 J jnl
CoRR
Mansoor Ahmed, Usama Sardar, Sarwan Ali, Shafiq Alam, Murray Patterson, Imdad Ullah Khan
2022 J jnl
Remote. Sens.
Maqsood Ahmed, Yonglin Shen, Mansoor Ahmed, Zemin Xiao, Ping Cheng, Nafees Ali, Abdul Ghaffar, Sabir Ali
2022 J jnl
Complex Intell. Syst.
Abid Khan, Awais Ahmad, Mansoor Ahmed, Jadran Sessa, Marco Anisetti
2022 J jnl
Trans. Emerg. Telecommun. Technol.
Ahmad Ali, Abid Khan, Mansoor Ahmed, Gwanggil Jeon
2022 J jnl
IEEE Access
Mansoor Ahmed, Naeem Iqbal, Faraz Hussain, Murad-Ali Khan, Markus Helfert, Imran, Jungsuk Kim
2021 J jnl
PeerJ Comput. Sci.
Mansoor Ahmed, Kainat Ansar, Cal B. Muckley, Abid Khan, Adeel Anjum, Muhammad Talha
2021 J jnl
IEEE Access
Usama Farooq, Mansoor Ahmed, Shahid Hussain, Faraz Hussain, Alia Naseem, Khurram Aslam
2021
Mansoor Ahmed
2021 J jnl
IEEE Access
Saira Beg, Adeel Anjum, Mansoor Ahmed, Saif Ur Rehman Malik, Hassan Malik, Navuday Sharma, Omer Waqar
2021 J jnl
IEEE Access
Muhammad Azeem Sarwar, Mansoor Ahmed, Asad Habib, Muhammad Khalid, M. Akhtar Ali, Mohsin Raza, Shahid Hussain, Ghufran Ahmed
2021 J jnl
Sensors
Faheem Zafar, Abid Khan, Saif Ur Rehman Malik, Mansoor Ahmed, Carsten Maple, Adeel Anjum
2021 Misc conf
FIT
Kaaenat Ali, Junaid Ali Khan, Farwah Aizaz, Mansoor Ahmed
2021 J jnl
PeerJ Comput. Sci.
Ahmad Ali, Mansoor Ahmed, Abid Khan, Adeel Anjum, Muhammad Ilyas, Markus Helfert
2020 J jnl
Int. J. Parallel Program.
Idrees Ahmed, Abid Khan, Adeel Anjum, Mansoor Ahmed, Muhammad Asif Habib
2020 J jnl
Multim. Tools Appl.
Moomina Waheed, Shahid Hussain, Arif Ali Khan, Mansoor Ahmed, Bashir Ahmad
2020 J jnl
IEEE Access
Komal Minhas, Tariq Mahmood Khan, Muhammad Arsalan, Syed Saud Naqvi, Mansoor Ahmed, Haroon Ahmed Khan, Muhammad Adnan Haider, Abdul Haseeb
2020 J jnl
IEEE Access
Munazza Tabassum, Tariq Mahmood Khan, Muhammad Arsalan, Syed Saud Naqvi, Mansoor Ahmed, Hussain Ahmed Madni, Jawad Mirza
2020 J jnl
IEEE Internet Things Mag.
Kamran Sattar Awaisi, Shahid Hussain, Mansoor Ahmed, Arif Ali Khan, Ghufran Ahmed
2020 J jnl
CoRR
Faheem Zafar, Abid Khan, Saif Ur Rehman Malik, Adeel Anjum, Mansoor Ahmed
2020 J jnl
Multim. Tools Appl.
Sidra Aslam, Mansoor Ahmed, Imran Ahmed, Abid Khan, Awais Ahmad, Muhammad Imran, Adeel Anjum, Shahid Hussain
2020 J jnl
Multim. Tools Appl.
Farah Naz, Abid Khan, Mansoor Ahmed, Majid Iqbal Khan, Sadia Din, Awais Ahmad, Gwanggil Jeon
2019 conf
WorldCIST (3)
Shaista Bibi, Shahid Hussain, Mansoor Ahmed, Muhammad Shahid Zeb
2019 J jnl
Commun. Nonlinear Sci. Numer. Simul.
Omer San, Romit Maulik, Mansoor Ahmed
2019 J jnl
Comput. Secur.
Idrees Ahmed, Abid Khan, Mansoor Ahmed, Saif Ur Rehman Malik
2018 C conf
ISNCC
Mansoor Ahmed, Abid Khan, Osama Saleem, Muhammad Haris
2018 J jnl
CoRR
Mansoor Ahmed, Kari Kostiainen
2018 J jnl
IEEE Access
Mansoor Ahmed, Lin Bai
2018 J jnl
Comput. Secur.
Fuzel Jamil, Abid Khan, Adeel Anjum, Mansoor Ahmed, Farhana Jabeen, Nadeem Javaid
2018 J jnl
Future Gener. Comput. Syst.
Khizar Hameed, Abid Khan, Mansoor Ahmed, Goutham Reddy Alavalapati, M. Mazhar Rathore
2018 J jnl
J. Supercomput.
Mubashar Hussain, Mansoor Ahmed, Hasan Ali Khattak, Muhammad Imran, Abid Khan, Sadia Din, Awais Ahmad, Gwanggil Jeon, Goutham Reddy Alavalapati
2017 J jnl
Comput. Secur.
Faheem Zafar, Abid Khan, Saif Ur Rehman Malik, Mansoor Ahmed, Adeel Anjum, Majid Iqbal Khan, Nadeem Javed, Masoom Alam, Fuzel Jamil
2017 C conf
ISNCC
Ahmad Ali, Mansoor Ahmed, Abid Khan, Muhammad Ilyas, Muhammad Saad Razzaq
2017 J jnl
J. Netw. Comput. Appl.
Sidra Aslam, Saif ul Islam, Abid Khan, Mansoor Ahmed, Adnan Akhunzada, Muhammad Khurram Khan
2017 conf
FDSE
Ahmad Ali, Mansoor Ahmed, Muhammad Ilyas, Josef Küng
2017 A* conf
USENIX Security Symposium
Sinisa Matetic, Mansoor Ahmed, Kari Kostiainen, Aritra Dhar, David M. Sommer, Arthur Gervais, Ari Juels, Srdjan Capkun
2017 J jnl
IACR Cryptol. ePrint Arch.
Sinisa Matetic, Mansoor Ahmed, Kari Kostiainen, Aritra Dhar, David M. Sommer, Arthur Gervais, Ari Juels, Srdjan Capkun
2017 conf
FNC/MobiSPC
Abid Khan, Ayyaz Yaqoob, Kinza Sarwar, Mouzna Tahir, Mansoor Ahmed
2017 J jnl
Comput. Secur.
Adeel Anjum, Guillaume Raschia, Marc Gelgon, Abid Khan, Saif Ur Rehman Malik, Naveed Ahmad, Mansoor Ahmed, Sabah Suhail, Masoom Alam
2016 J jnl
KSII Trans. Internet Inf. Syst.
Faheem Zafar, Abid Khan, Mansoor Ahmed, Majid Iqbal Khan, Farhana Jabeen, Zara Hamid, Naveed Ahmed, Faisal Bashir Hussain
2016 conf
Trustcom/BigDataSE/ISPA
Idrees Ahmed, Abid Khan, Muhammad Saleem Khan, Mansoor Ahmed
2016 J jnl
J. Netw. Comput. Appl.
Abid Khan, Farhana Jabeen, Farah Naz, Sabah Suhail, Mansoor Ahmed, Sarfraz Nawaz
2016 J jnl
Sensors
Sidrah Yousaf, Nadeem Javaid, Umar Qasim, Nabil Ali Alrajeh, Zahoor Ali Khan, Mansoor Ahmed
2014 conf
ICACCI
Mansoor Ahmed, Anirudh Sriram, Sanjay Singh
2011 conf
ICBO
Stella Mitchell, Carlo Torniai, Brian Lowe, Jon Corson-Rikert, Melanie Wilson, Mansoor Ahmed, Shanshan Chen, Ying Ding, Nicholas Rejack, Melissa A. Haendel
2010 B conf
ARES
Mansoor Ahmed, Amin Anjomshoaa, Muhammad Asfand-e-yar, A Min Tjoa, Abid Khan
2009 Misc conf
FIT
Usman Sharif, Abid Khan, Mansoor Ahmed, Muhammad Waqas Anwar, Ali Nawaz Khan
2009 Misc conf
FIT
Abid Khan, Xiamu Niu, Waqas Anwar, Mansoor Ahmed, Ali Nawaz Khan
2008 C conf
iiWAS
Mansoor Ahmed, Amin Anjomshoaa, A Min Tjoa
2007 B conf
ARES
Mansoor Ahmed, Amin Andjomshoaa, Tho Manh Nguyen, A Min Tjoa
2007 C conf
iiWAS
Mansoor Ahmed, Amin Andjomshoaa, A Min Tjoa
2004 C conf
iiWAS
Mansoor Ahmed, Hanh Huu Hoang, Muhammad Shuaib Karim, Shah Khusro, Monika Lanzenberger, Khalid Latif, Elke Michlmayr, Khabib Mustofa, H. T. Nguyen, Andreas Rauber, Alexander Schatten, Tho Manh Nguyen, A Min Tjoa
2001 conf
VTC Fall
Mansoor Ahmed, Joseph Pautler, Kamyar Rohani
2001 conf
VTC Fall
Joseph Pautler, Mansoor Ahmed, Kamyar Rohani
redb/extractors/decompiler/bninja/analysis/disassembly.py
← Index redb/extractors/decompiler/bninja/analysis/disassembly.py python
import re
import time

import binaryninja
from binaryninja.enums import (
    InstructionTextTokenType,
)

# Support both package and standalone imports
try:
    from ..function_type import FunctionTypeAnalysis
    from ..utils.hashes import calculate_sha256
except ImportError:
    # Fallback to absolute imports (for multiprocessing spawned processes)
    from redb.extractors.decompiler.bninja.function_type import FunctionTypeAnalysis
    from redb.extractors.decompiler.bninja.utils.hashes import calculate_sha256


class DisassemblyAnalysis:
    INVALID_STACK_SIZE = -1

    def __init__(self, arch, function, bv, logger):
        self.arch = arch
        self.function = function
        self.bv = bv
        self.logger = logger
        if self.function is not None and hasattr(self.function, "instructions"):
            self.instructions = self.function.instructions
        else:
            self.instructions = []
        self.errors = []
        return

    def log_error(
        self, message, function_name, address, exception=None, error_location="unknown"
    ):
        """Log an error during processing."""
        error_msg = f"Error in function {function_name} at {address}: {message}"
        if exception:
            error_msg += f" - {str(exception)}"
        self.logger.error(error_msg)

        # Add to errors list
        error = {
            "function_name": function_name,
            "function_address": str(address),
            "error_location": error_location,
            "error_message": message,
            "error_details": str(exception) if exception else "",
            "error_type": type(exception).__name__ if exception else "Unknown",
            "timestamp": int(time.time() * 1000),
        }
        self.errors.append(error)

    def get_json(self):
        try:
            # Build disassembly string and normalized versions
            disassembly_builder = [[], []]  # Address and instruction text

            # Create a dictionary mapping addresses to instruction tokens
            instr_tokens_by_addr = {}
            for instr_tokens, addr in self.instructions:
                instr_tokens_by_addr[addr] = instr_tokens

            addresses = sorted(instr_tokens_by_addr.keys())
            for address in addresses:
                # Original disassembly with addresses
                # instr_tokens, address = instruction
                instr_tokens = instr_tokens_by_addr[address]
                disassembly_builder[0].append(address)
                disassembly_builder[1].append("".join(map(str, instr_tokens)))

            # Join with newlines
            disassembly_str = "\n".join(disassembly_builder[1])
            disassembly_with_addresses = "\n".join(
                f"{hex(address)}: {instr_text}"
                for address, instr_text in zip(
                    disassembly_builder[0], disassembly_builder[1], strict=False
                )
            )

            disassembly_json = {
                "disassembled_function_hash": calculate_sha256(disassembly_str),
                "disassembled_function": disassembly_with_addresses,
                "disassembled_function_no_addresses": disassembly_str,
                "disassembled_function_name": self.function.name,
                "disassembled_function_address": self.function.start,
                "instructions_count": len(instr_tokens_by_addr.keys()),
                "function_type": FunctionTypeAnalysis(self.function)
                .get_function_type()
                .name,
            }

            # Add additional metrics
            type_frequencies = self.collect_instruction_types()
            disassembly_json["instructions_types"] = list(type_frequencies.keys())
            disassembly_json["control_flow_count"] = (
                self.count_control_flow_instructions()
            )
            disassembly_json["memory_access_pattern"] = self.collect_memory_patterns()
            disassembly_json["register_usage"] = self.collect_register_usage()
            disassembly_json["data_references_count"] = self.count_data_references()
            disassembly_json["max_block_size"] = self.compute_max_block_size()
            disassembly_json["num_calls"] = self.compute_num_calls()
            disassembly_json["stack_size"] = self.estimate_stack_size()

            return disassembly_json, self.errors

        except Exception as e:
            self.log_error(
                "Failed to collect instruction types",
                self.function.name,
                self.function.start,
                e,
                "collect_instruction_types",
            )
            raise ValueError(e) from e

    def collect_instruction_types(self):
        """Collect instruction type frequencies from a function."""
        type_frequencies = {}

        try:
            # Iterate through all instructions in the function
            for instruction in self.instructions:
                instr_tokens = instruction[0]  # Get the instruction tokens

                # Extract the mnemonic from the instruction tokens
                mnemonic = None
                for token in instr_tokens:
                    if token.type == InstructionTextTokenType.InstructionToken:
                        mnemonic = token.text
                        break

                if not mnemonic:
                    continue

                # Use normalize_opcode to get standardized opcode
                normalized = self.normalize_opcode(mnemonic)

                # Get category from opcode_categories or use the instruction type directly
                category = self.arch.opcode_categories.get(normalized)
                if category:
                    self._increment_frequency(type_frequencies, category)

        except Exception as e:
            self.log_error(
                "Failed to collect instruction types",
                self.function.name,
                self.function.start,
                e,
                "collect_instruction_types",
            )

        return type_frequencies

    def normalize_opcode(self, opcode):
        return opcode.upper()

    def collect_memory_patterns(self):
        """Collect memory access patterns from a function."""
        patterns = []
        try:
            for instruction in self.instructions:
                instr_tokens = instruction[0]

                # We need to capture memory operands between BeginMemoryOperandToken and EndMemoryOperandToken
                in_memory_operand = False
                memory_operand_text = ""

                for token in instr_tokens:
                    if token.type == InstructionTextTokenType.BeginMemoryOperandToken:
                        in_memory_operand = True
                        memory_operand_text = ""
                    elif token.type == InstructionTextTokenType.EndMemoryOperandToken:
                        in_memory_operand = False

                        # Process the captured memory operand text
                        if memory_operand_text:
                            # Categorize memory access pattern
                            if (
                                "+" in memory_operand_text
                                and "*" in memory_operand_text
                            ):
                                if "MEM_SCALED_INDEX" not in patterns:
                                    patterns.append("MEM_SCALED_INDEX")
                            elif (
                                "+" in memory_operand_text or "-" in memory_operand_text
                            ):
                                if "MEM_BASE_OFFSET" not in patterns:
                                    patterns.append("MEM_BASE_OFFSET")
                            else:
                                if "MEM_DIRECT" not in patterns:
                                    patterns.append("MEM_DIRECT")

                            # Check for stack accesses
                            if any(
                                reg in memory_operand_text
                                for reg in ["SP", "BP", "ESP", "EBP", "RSP", "RBP"]
                            ):
                                if "MEM_STACK" not in patterns:
                                    patterns.append("MEM_STACK")
                            # Check for string operations
                            elif (
                                any(
                                    reg in memory_operand_text
                                    for reg in ["SI", "DI", "ESI", "EDI", "RSI", "RDI"]
                                )
                                and "MEM_STRING" not in patterns
                            ):
                                patterns.append("MEM_STRING")
                    elif in_memory_operand:
                        # Accumulate token text while inside a memory operand
                        memory_operand_text += token.text
        except Exception as e:
            self.log_error(
                "Failed to collect memory patterns",
                self.function.name,
                self.function.start,
                e,
                "collect_memory_patterns",
            )
        return patterns

    def collect_register_usage(self):
        """Collect register usage from a function."""
        registers = []
        try:
            # Define register groups we're interested in tracking
            register_groups = {
                "GPR": [
                    "RAX",
                    "RBX",
                    "RCX",
                    "RDX",
                    "R9",
                    "R10",
                    "R11",
                    "R12",
                    "R13",
                    "R14",
                    "R15",
                    "EAX",
                    "EBX",
                    "ECX",
                    "EDX",
                    "R9D",
                    "R10D",
                    "R11D",
                    "R12D",
                    "R13D",
                    "R14D",
                    "AX",
                    "BX",
                    "CX",
                    "DX",
                ],
                "GPR_INDEX": ["RSI", "RDI", "ESI", "EDI", "SI", "DI"],
                "GPR_STACK": ["RSP", "RBP", "ESP", "EBP", "SP", "BP"],
                "SIMD": ["XMM", "YMM", "ZMM"],
                "FPU": ["ST", "ST0", "ST1", "ST2", "ST3", "ST4", "ST5", "ST6", "ST7"],
                "FLAGS": ["FLAGS", "EFLAGS", "RFLAGS"],
                "CONTROL_REGISTER": ["CR0", "CR2", "CR3", "CR4", "CR8"],
                "DEBUG_REGISTER": ["DR0", "DR1", "DR2", "DR3", "DR6", "DR7"],
            }

            # Extract registers from instructions
            for instruction in self.instructions:
                instr_tokens = instruction[0]
                for token in instr_tokens:
                    if token.type == InstructionTextTokenType.RegisterToken:
                        reg = token.text.upper()
                        # Check which group this register belongs to
                        for group, regs in register_groups.items():
                            # if any(r in reg for r in regs) or any(reg.startswith(r) for r in regs):
                            if any(reg == r or reg.startswith(r) for r in regs):
                                if group not in registers:
                                    registers.append(group)
                                break
        except Exception as e:
            self.log_error(
                "Failed to collect register usage",
                self.function.name,
                self.function.start,
                e,
                "collect_register_usage",
            )
        return registers

    def count_data_references(self):
        """Count the number of data references in a function."""
        count = 0
        try:

            if self.function.mlil is None:
                return 0

            for block in self.function.mlil:
                for instr in block:
                    instr_str = str(instr)
                    logged = False
                    src = None

                    # Check for constant dereferencing or symbolic refs
                    if hasattr(instr, "src"):
                        src = instr.src
                        if isinstance(
                            src,
                            (
                                binaryninja.mediumlevelil.MediumLevelILConstPtr,
                                binaryninja.mediumlevelil.MediumLevelILConst,
                            ),
                        ):
                            count += 1
                            logged = True

                    # Check full string for hardcoded addresses or symbol-like tokens
                    if re.search(r"\b0x[0-9A-Fa-f]{3,}\b", instr_str) and not logged:
                        count += 1
                        logged = True

                    if "_" in instr_str and not logged:
                        count += 1
                        logged = True

                    # Only check for MediumLevelILConstPtr if src exists
                    if src is not None and isinstance(
                        src, binaryninja.mediumlevelil.MediumLevelILConstPtr
                    ):
                        addr = src.constant
                        # Check if address is in data sections
                        segment = self.bv.get_segment_at(addr)
                        if segment and segment.writable:
                            # print(f"[{function.name}] Matched data section reference in: {instr_str}")
                            count += 1
                            logged = True
        except Exception as e:
            self.logger.warning(
                f"Failed to use MLIL for counting data references in {self.function.name} at {self.function.start}: {e}"
            )
        return count

    def compute_max_block_size(self):
        """Compute the maximum basic block size in a function."""
        max_size = 0
        if self.function is None:
            return 0

        for block in self.function.basic_blocks:
            try:
                # Count instructions in this block using the direct length approach
                # This avoids UTF-8 decoding issues entirely
                block_size = block.instruction_count
                max_size = max(max_size, block_size)
            except Exception as e:
                self.log_error(
                    f"[HandledError] computing max block size: {e}",
                    self.function.name,
                    self.function.start,
                    e,
                    "compute_max_block_size",
                )
        return max_size

    def count_control_flow_instructions(self):
        """Count the number of control flow instructions in a function."""
        count = 0
        try:
            for instruction in self.instructions:
                instr_tokens = instruction[0]
                if self.arch.is_control_flow_instruction(instr_tokens):
                    count += 1
        except Exception as e:
            self.log_error(
                "Failed to count control flow instructions",
                self.function.name,
                self.function.start,
                e,
                "count_control_flow_instructions",
            )
        return count

    def compute_num_calls(self) -> int:
        """Compute the number of call instructions in a function."""
        num_calls = 0
        try:
            for instruction in self.instructions:
                instr_tokens = instruction[0]
                # Extract the mnemonic
                for token in instr_tokens:
                    if token.type == InstructionTextTokenType.InstructionToken:
                        if token.text.upper() == "CALL":
                            num_calls += 1
                        break
        except Exception as e:
            self.log_error(
                "Failed to compute number of calls",
                self.function.name,
                self.function.start,
                e,
                "compute_num_calls",
            )
        return num_calls

    def _increment_frequency(self, frequencies, type_name):
        """Increment the frequency count for an instruction type."""
        if type_name in frequencies:
            frequencies[type_name] += 1
        else:
            frequencies[type_name] = 1

    def estimate_stack_size(self):
        """Estimate the stack size used by a function."""
        try:
            # Binary Ninja provides a stack adjustment value for functions
            # Need to convert OffsetWithConfidence to a plain integer
            stack_adjust = self.function.stack_adjustment
            if hasattr(stack_adjust, "value"):  # Handle OffsetWithConfidence objects
                return stack_adjust.value
            return stack_adjust
        except Exception as e:
            self.log_error(
                "Failed to estimate stack size",
                self.function.name,
                self.function.start,
                e,
                "estimate_stack_size",
            )
            return self.INVALID_STACK_SIZE