Skip to main content

Analysis Overview

Ghidra’s analysis system is a sophisticated pipeline that automatically processes programs to identify functions, data structures, references, and other program semantics. The system is designed to be extensible, prioritized, and incremental.

Auto-Analysis Manager

The AutoAnalysisManager coordinates all analysis activities for a program:
// From ghidra/app/plugin/core/analysis/AutoAnalysisManager.java:57-63
public class AutoAnalysisManager {
    // Manages analysis task scheduling
    private AnalysisTaskList byteTasks;
    private AnalysisTaskList functionTasks;
    private AnalysisTaskList instructionTasks;
    private AnalysisTaskList dataTasks;
    
    public static AutoAnalysisManager getAnalysisManager(Program program);
    public void startAnalysis(TaskMonitor monitor);
    public void reAnalyzeAll(AddressSetView addresses);
}
Key Responsibilities:
  • Schedule analyzers by priority
  • Manage address sets for incremental analysis
  • Coordinate parallel analysis tasks
  • Track analysis state and progress
  • Handle analysis events and dependencies
From ghidra/app/plugin/core/analysis/AutoAnalysisManager.java:63-150

Analyzer Interface

All analyzers implement the Analyzer interface:
// From ghidra/app/services/Analyzer.java:27-44
public interface Analyzer extends ExtensionPoint {
    // Analyzer identification
    String getName();
    String getDescription();
    AnalyzerType getAnalysisType();
    
    // Configuration
    AnalysisPriority getPriority();
    boolean getDefaultEnablement(Program program);
    boolean canAnalyze(Program program);
    
    // Analysis callbacks
    boolean added(Program program, AddressSetView set, 
                  TaskMonitor monitor, MessageLog log);
    boolean removed(Program program, AddressSetView set,
                   TaskMonitor monitor, MessageLog log);
    
    // Options management
    void registerOptions(Options options, Program program);
    void optionsChanged(Options options, Program program);
    void analysisEnded(Program program);
}

Analyzer Properties

Name

Unique identifier for the analyzer

Type

Classification (bytes, instructions, functions, data)

Priority

Execution order relative to other analyzers

Enablement

Default enabled/disabled state

Analysis Types

Analyzers are categorized by what they analyze:
public enum AnalyzerType {
    BYTE_ANALYZER,        // Process raw bytes
    INSTRUCTION_ANALYZER, // Analyze instructions
    FUNCTION_ANALYZER,    // Analyze functions
    FUNCTION_MODIFIERS_ANALYZER,    // Function properties
    FUNCTION_SIGNATURES_ANALYZER,   // Function signatures
    DATA_ANALYZER         // Analyze data
}
Analysis Order:
1

Byte Analysis

Process raw bytes to identify patterns and structures
2

Instruction Analysis

Analyze disassembled instructions and code flow
3

Function Analysis

Identify and analyze function boundaries and properties
4

Data Analysis

Identify and type data structures

Analyzer Priorities

Priority determines execution order within each analysis type:
public class AnalysisPriority {
    public static final AnalysisPriority BLOCK_ANALYSIS;
    public static final AnalysisPriority DISASSEMBLY;
    public static final AnalysisPriority CODE_ANALYSIS;
    public static final AnalysisPriority FUNCTION_ID_ANALYSIS;
    public static final AnalysisPriority FUNCTION_ANALYSIS;
    public static final AnalysisPriority DATA_TYPE_PROPOGATION;
    public static final AnalysisPriority DATA_ANALYSIS;
    public static final AnalysisPriority REFERENCE_ANALYSIS;
}
Priority Guidelines:
  • Lower numbers run first
  • Disassembly before function analysis
  • Function analysis before data propagation
  • Reference analysis runs late

Built-in Analyzers

Ghidra includes many standard analyzers:

Core Analyzers

Converts bytes to instructions at entry points and code references.Priority: Very High
Type: Instruction Analyzer
DisassembleCommand cmd = new DisassembleCommand(addr, null, true);
cmd.applyTo(program, monitor);
Uses decompiler to identify function parameters and return values.Priority: Medium
Type: Function Signatures Analyzer
Requires the decompiler to be available.
Analyzes stack frame usage to identify local variables and parameters.Priority: Medium
Type: Function Analyzer
Identifies data references from code:
  • Immediate operands
  • Memory references
  • String references
Priority: Low
Type: Instruction Analyzer
Demangles C++ and other mangled symbol names.Priority: Low
Type: Function Analyzer
Supports multiple demangling schemes (GNU, Microsoft, etc.)

Writing Custom Analyzers

Basic Analyzer Template

import ghidra.app.services.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.framework.options.Options;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.Program;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;

public class MyAnalyzer extends AbstractAnalyzer {
    
    public MyAnalyzer() {
        super("My Analyzer", "Description of what it does", 
              AnalyzerType.INSTRUCTION_ANALYZER);
        // Set priority
        setPriority(AnalysisPriority.CODE_ANALYSIS);
        // Default to enabled
        setDefaultEnablement(true);
        // Supports one-time analysis
        setSupportsOneTimeAnalysis(true);
    }
    
    @Override
    public boolean canAnalyze(Program program) {
        // Check if this analyzer applies to this program
        return true;
    }
    
    @Override
    public boolean added(Program program, AddressSetView set, 
                        TaskMonitor monitor, MessageLog log)
            throws CancelledException {
        
        // Perform analysis
        monitor.setMessage("Running My Analyzer...");
        monitor.initialize(set.getNumAddresses());
        
        AddressIterator iter = set.getAddresses(true);
        while (iter.hasNext()) {
            monitor.checkCancelled();
            Address addr = iter.next();
            
            // Analyze this address
            analyzeAddress(program, addr, monitor, log);
            
            monitor.incrementProgress(1);
        }
        
        return true;
    }
    
    private void analyzeAddress(Program program, Address addr,
                               TaskMonitor monitor, MessageLog log) {
        // Your analysis logic here
        Instruction inst = program.getListing().getInstructionAt(addr);
        if (inst != null) {
            // Process instruction
        }
    }
    
    @Override
    public void registerOptions(Options options, Program program) {
        // Register analyzer options
        options.registerOption("My Option", true, null,
            "Description of this option");
    }
    
    @Override
    public void optionsChanged(Options options, Program program) {
        // Read option values
        boolean myOption = options.getBoolean("My Option", true);
    }
}
Analyzer class names must end with “Analyzer” to be discovered by the ClassSearcher system.

Analyzer Best Practices

Always check for cancellation in loops:
monitor.checkCancelled();
Keep the user informed:
monitor.setMessage("Analyzing functions...");
monitor.initialize(total);
monitor.incrementProgress(1);
Use the MessageLog:
log.appendMsg("Found " + count + " patterns");
log.appendException(e);
Wrap modifications in transactions:
int txId = program.startTransaction("My Analysis");
try {
    // Make changes
    program.endTransaction(txId, true);
} catch (Exception e) {
    program.endTransaction(txId, false);
}
Document analyzer dependencies and set appropriate priorities.

Analysis Lifecycle

Starting Analysis

Analysis can be triggered multiple ways:
// Automatic on import
AutoAnalysisManager.getAnalysisManager(program)
    .scheduleWorker(new AutoAnalysisWorker(monitor));

// Manual via API
AutoAnalysisManager mgr = AutoAnalysisManager.getAnalysisManager(program);
mgr.startAnalysis(monitor);

// Incremental analysis on specific addresses
AddressSet set = new AddressSet(addr1, addr2);
mgr.reAnalyzeAll(set);

Analysis Flow

Analysis Tasks

Tasks are queued for each analyzer and address range:
private class AnalysisTaskList {
    void addTask(AnalyzerAdapter analyzer, AddressSetView set);
    AnalysisTask getNextTask();
    boolean hasMoreTasks();
}
From ghidra/app/plugin/core/analysis/AutoAnalysisManager.java:96-103

Parallel Analysis

Some analyzers support parallel execution:
// Get shared thread pool
GThreadPool pool = GThreadPool.getSharedThreadPool(
    AutoAnalysisManager.SHARED_THREAD_POOL_NAME
);

// Submit parallel tasks
pool.submit(() -> {
    analyzeRange(range1);
});
pool.submit(() -> {
    analyzeRange(range2);
});

// Wait for completion
pool.waitForAll();
When using parallel analysis, ensure proper synchronization when accessing shared program resources.

Analysis Options

Analyzers can be configured via the analysis options:
Options options = program.getOptions(Program.ANALYSIS_PROPERTIES);

// Get analyzer-specific options
Options analyzerOptions = options.getOptions("My Analyzer");
boolean enabled = analyzerOptions.getBoolean("My Option", true);

// Set options
analyzerOptions.setBoolean("My Option", false);

Common Options

  • Enable/disable specific analyzers
  • Configure analyzer-specific behavior
  • Set analysis boundaries
  • Control aggressiveness

Analysis State

Programs track whether they’ve been analyzed:
Options info = program.getOptions(Program.PROGRAM_INFO);

// Check if analyzed
boolean analyzed = info.getBoolean(Program.ANALYZED_OPTION_NAME, false);

// Mark as analyzed
info.setBoolean(Program.ANALYZED_OPTION_NAME, true);

// Control analysis prompt
info.setBoolean(Program.ASK_TO_ANALYZE_OPTION_NAME, true);
From ghidra/program/model/listing/Program.java:61-64

Incremental Analysis

Ghidra supports incremental re-analysis:
// Re-analyze specific addresses
AddressSet changedAddrs = new AddressSet();
changedAddrs.add(addr1, addr2);

AutoAnalysisManager mgr = AutoAnalysisManager.getAnalysisManager(program);
mgr.reAnalyzeAll(changedAddrs);
Triggers for Incremental Analysis:
  • User clears code/data
  • Function boundaries change
  • New memory blocks added
  • Data types modified

Analysis Performance

Optimization Tips

Process addresses in batches:
AddressRangeIterator ranges = set.getAddressRanges();
while (ranges.hasNext()) {
    AddressRange range = ranges.next();
    processRange(range);
}
Avoid repeated lookups:
Memory memory = program.getMemory();
SymbolTable symbolTable = program.getSymbolTable();
// Use cached references
AddressSet is optimized for range operations:
AddressSet set = new AddressSet();
set.add(new AddressRangeImpl(start, end));
Batch related changes:
int txId = program.startTransaction("Batch update");
try {
    // Multiple changes
    program.endTransaction(txId, true);
}

Debugging Analyzers

Logging

import ghidra.util.Msg;

public class MyAnalyzer extends AbstractAnalyzer {
    @Override
    public boolean added(Program program, AddressSetView set,
                        TaskMonitor monitor, MessageLog log) {
        
        Msg.debug(this, "Starting analysis at " + set.getMinAddress());
        Msg.info(this, "Found " + count + " items");
        Msg.warn(this, "Potential issue detected");
        Msg.error(this, "Analysis failed", exception);
        
        return true;
    }
}

Testing

@Test
public void testMyAnalyzer() throws Exception {
    Program program = createTestProgram();
    
    MyAnalyzer analyzer = new MyAnalyzer();
    AddressSet set = new AddressSet(addr(0x1000), addr(0x2000));
    MessageLog log = new MessageLog();
    
    boolean success = analyzer.added(program, set, 
                                     TaskMonitor.DUMMY, log);
    
    assertTrue(success);
    // Verify analysis results
}

Analysis Events

Monitor analysis progress:
public interface AutoAnalysisManagerListener {
    void analysisStarted(Program program);
    void analysisEnded(Program program);
    void analyzerStatusChanged(String analyzerName, boolean enabled);
}

AutoAnalysisManager mgr = AutoAnalysisManager.getAnalysisManager(program);
mgr.addListener(new AutoAnalysisManagerListener() {
    @Override
    public void analysisEnded(Program program) {
        Msg.info(this, "Analysis complete");
    }
});

Best Practices

  • Keep analyzers focused on one task
  • Document dependencies and requirements
  • Provide meaningful options
  • Handle edge cases gracefully
  • Minimize database access
  • Use efficient data structures
  • Consider parallel execution
  • Profile and optimize hot paths
  • Provide clear progress feedback
  • Allow cancellation
  • Log important findings
  • Document what the analyzer does
  • Test on diverse programs
  • Verify correctness
  • Check performance
  • Test cancellation behavior

Next Steps

Programs

Learn about the program model

Projects

Understand project organization

Architecture

Explore framework architecture

Overview

Return to framework overview

Build docs developers (and LLMs) love