# How Ghidra Manages Memory and Address Spaces in Reverse Engineering

> Discover how Ghidra manages memory and address spaces for reverse engineering. Learn about distinct namespaces for RAM, registers, stacks, and constants within each program.

- Repository: [National Security Agency/ghidra](https://github.com/NationalSecurityAgency/ghidra)
- Tags: internals
- Published: 2026-03-04

---

**Ghidra represents program memory through a hierarchy of immutable `AddressSpace` objects created by an `AddressFactory`, where each `Program` instance maintains unique physical and overlay spaces that isolate RAM, registers, stacks, and constants into distinct namespaces.**

Ghidra’s memory model is fundamental to its reverse engineering capabilities, enabling accurate disassembly and decompilation across diverse processor architectures. According to the NationalSecurityAgency/ghidra source code, the framework implements a type-safe, space-aware addressing system that prevents accidental cross-space address manipulation while supporting complex memory layouts including overlays and Harvard architectures.

## Core Architecture of Ghidra Memory Management

### AddressSpace and GenericAddressSpace

At the foundation of Ghidra memory management lies the **`AddressSpace`** interface, defined in [`Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressSpace.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressSpace.java). This immutable object identifies a namespace for addresses, encapsulating:

- **Name** (e.g., "ram", "register", "stack")
- **Size** (addressable range)
- **Type** (ram, register, stack, constant, unique, other)
- **Unique ID** (compact integer for fast indexing)

The concrete implementation **`GenericAddressSpace`**, located in [`Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/GenericAddressSpace.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/GenericAddressSpace.java), provides the standard behavior for most built-in spaces. Addresses from different spaces are never interchangeable, preventing architectural errors during analysis.

### AddressFactory and Address Creation

Each `Program` instance owns a unique **`AddressFactory`**, implemented in [`Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressFactory.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressFactory.java). This factory serves as the central authority for:

- Creating `Address` objects via `getAddress(String)` and `getAddress(long)`
- Parsing address strings such as `ram:0x1000` or `0x1000` (default space)
- Enumerating available spaces through `getAddressSpaces()` and `getAddressSpace(String)`
- Determining if multiple memory spaces exist via `hasMultipleMemorySpaces()` (critical for Harvard architectures)

## Memory Blocks and Physical Layout

### Memory and MemoryBlock Interfaces

The **`Memory`** interface, defined in [`Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java), represents the collection of **`MemoryBlock`** instances that occupy one or more address spaces. Each `MemoryBlock`, detailed in [`Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlock.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlock.java), represents a contiguous region of bytes associated with a specific `AddressSpace`.

The database-backed implementation **`MemoryBlockDB`** in [`Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryBlockDB.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryBlockDB.java) provides the runtime persistence layer for these blocks.

### Block Types and Permissions

Ghidra supports several memory block types through the `Memory` interface:

- **Initialized blocks**: Contain actual byte values loaded from the binary
- **Uninitialized blocks**: Reserve address ranges without backing storage
- **Byte-mapped blocks**: Map existing memory to a new address range
- **Bit-mapped blocks**: Map individual bits for packed bit fields
- **Overlay blocks**: Create alternate views of physical memory

Each block maintains permissions (read, write, execute) and flags indicating whether it is loaded, volatile, or part of the overlay system.

## Working with Address Spaces in Code

The following examples demonstrate how to interact with Ghidra's memory and address space APIs using the core framework classes.

```java
// ------------------------------------------------------------
// 1. Obtain the address factory from a program
// ------------------------------------------------------------
Program prog = ...;                     // a loaded Program instance
AddressFactory af = prog.getAddressFactory();

// ------------------------------------------------------------
// 2. Look up a known space (e.g., RAM) and create an address
// ------------------------------------------------------------
AddressSpace ram = af.getAddressSpace("ram");
Address addr = ram.getAddress(0x0010_0000L);   // 0x00100000 in RAM

// ------------------------------------------------------------
// 3. Create an initialized memory block in RAM
// ------------------------------------------------------------
Memory mem = prog.getMemory();
mem.createInitializedBlock(
        "myData",               // block name
        addr,                   // start address
        new ByteArrayInputStream(new byte[]{0x01,0x02,0x03,0x04}),
        4,                      // length
        new TaskMonitorAdapter(),
        false);                 // not an overlay

// ------------------------------------------------------------
// 4. Iterate over all loaded/initialized addresses
// ------------------------------------------------------------
AddressSetView initSet = mem.getLoadedAndInitializedAddressSet();
AddressIterator it = initSet.getAddresses(true);
while (it.hasNext()) {
    Address a = it.next();
    byte b = mem.getByte(a);
    // process byte...
}

```

## Overlay Address Spaces and Alternate Views

Overlay blocks provide a mechanism to create alternate views of physical memory without modifying the original layout. This is particularly useful for analyzing patched firmware or modified code paths.

```java
// ------------------------------------------------------------
// 5. Create an overlay block (alternative view)
// ------------------------------------------------------------
Address overlayStart = af.getAddressSpace("ram").getAddress(0x2000);
mem.createInitializedBlock(
        "overlayPatch",
        overlayStart,
        null,           // zero‑initialized
        0x100,          // 256 bytes
        new TaskMonitorAdapter(),
        true);          // <‑‑ overlay flag

// ------------------------------------------------------------
// 6. Determine the physical space of an overlay address
// ------------------------------------------------------------
Address overlayAddr = overlayStart.add(0x10);
AddressSpace overlaySpace = overlayAddr.getAddressSpace();
AddressSpace physical = overlaySpace.getPhysicalSpace(); // == ram

```

When an overlay block is created, Ghidra instantiates a new **overlay address space** with a distinct name while maintaining a reference to the underlying physical space via `getPhysicalSpace()`. This allows analysis tools to treat patched regions independently while preserving the relationship to the original memory layout.

## Address Space Properties and Implementation Details

### Space IDs and Fast Indexing

Each `AddressSpace` maintains a compact integer **space ID** accessible via `getSpaceID()`. The encoding utilizes bit masks (`ID_SIZE_MASK`, `ID_TYPE_MASK`) defined in [`AddressSpace.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/AddressSpace.java) to pack type information and size constraints into the ID for fast array indexing and comparison operations.

### Addressable Unit Size and Offset Handling

Spaces may define an **addressable unit size** through `getAddressableUnitSize()`, which specifies the number of bytes per addressable word. This is critical for architectures where a single address refers to multi-byte words (e.g., 4-byte word spaces). The conversion between byte offsets and addressable word offsets is handled internally by the space implementation.

Certain space types, particularly `TYPE_STACK`, utilize **signed offsets** indicated by `hasSignedOffset()`. Arithmetic operations such as `add`, `subtract`, and `truncateOffset` apply appropriate sign-extension semantics based on the space type, ensuring correct behavior for stack-relative addressing and other signed offset contexts.

## Summary

- **AddressSpace** objects provide immutable namespaces that isolate RAM, registers, stacks, and constants, preventing cross-space address confusion.
- **AddressFactory** serves as the central authority for creating addresses and managing the collection of spaces associated with a **Program**.
- **Memory** and **MemoryBlock** interfaces model physical memory layout, supporting initialized, uninitialized, mapped, and overlay block types.
- **Overlay address spaces** create alternate views of physical memory via `getPhysicalSpace()`, enabling analysis of patched firmware without modifying base layouts.
- Space-specific properties including **space IDs**, **addressable unit sizes**, and **signed offset handling** ensure architecture-accurate address arithmetic.

## Frequently Asked Questions

### What is the difference between an AddressSpace and a MemoryBlock in Ghidra?

An **AddressSpace** is an immutable namespace that defines a range of valid addresses (such as RAM or registers), while a **MemoryBlock** is a contiguous region of bytes that occupies a specific range within an AddressSpace. Multiple MemoryBlocks can exist within the same AddressSpace, but addresses from different AddressSpaces are never interchangeable.

### How does Ghidra handle Harvard architecture processors with separate code and data spaces?

Ghidra's **AddressFactory** detects multiple memory spaces via `hasMultipleMemorySpaces()`, returning **true** for Harvard architectures. The factory maintains separate AddressSpace instances for code and data (e.g., "ram" and "rom"), and analysis passes treat each space independently while the Program model coordinates between them.

### What is an overlay memory block and when should I use one?

An **overlay memory block** creates an alternate view of existing physical memory by instantiating a new overlay AddressSpace that maps to the same underlying bytes via `getPhysicalSpace()`. Use overlays when analyzing patched firmware, modified code paths, or alternative memory mappings that should remain isolated from the original program layout to prevent corruption of the base analysis.

### How are address space IDs used for performance optimization?

Each AddressSpace encodes a compact integer **space ID** using bit masks (`ID_SIZE_MASK`, `ID_TYPE_MASK`) that pack type and size information into a single integer. These IDs enable fast array indexing and comparison operations throughout Ghidra's analysis engine, avoiding expensive string comparisons when validating address ranges or performing arithmetic operations.