# Decompiler

### Overview

The Decompiler plug-in is a sophisticated transformation engine which automatically converts the binary representation of individual functions into a high-level C representation. The Decompiler presents a view of a program which is interactive and dynamically updated as the user adds or makes changes to the annotations associated with the program. A Decompiler window maintains the correspondence between the C representation and the assembly representation displayed in the Code Browser window, to the extent possible. The window allows instant visual association and navigation between C language expressions and their corresponding assembly instructions.

#### Enabling the Plug-in

The Decompiler is a full Plug-in within Ghidra and can be configured to be enabled or disabled within any particular tool. Default configurations will have the plug-in enabled, but if it is disabled for some reason, it can be enabled from within a Code Browser by selecting the

File -> Configure...
menu option, then clicking on the Configure link under the Ghidra Core section and checking the box next to DecompilePlugin.

#### Decompiling a Function

From the Code Browser, to open a Decompiler window, either:

- Press the icon in the tool bar, or
- Select the Decompile option from the Window menu.

The window automatically decompiles and displays the function at the current address. The address is set typically by left-clicking in the Listing, or invoking the Go To... command (pressing the 'G' key) and manually entering the address or some other label, but the Decompiler window follows any type of navigation in the Code Browser, triggering decompilation of the new function being displayed.

Any change to the function or Program made while using Ghidra causes the window to automatically redecompile the function it is displaying, to incorporate the new information. Changes include (but aren't limited to):

- Renaming Variables
- Setting Data-types
- Commenting
- Setting a Function's Prototype

Users can control decompilation in a wide variety of ways, see .

#### Capabilities

Some of the primary capabilities of the Decompiler include:

Recovering Expressions

  The Decompiler does full data-flow analysis which allows it to perform slicing on functions: complicated expressions, which have been split into distinct operations/instructions and then mixed together with other instructions by the compiling/optimizing process, are reconstituted back into a single line.

Recovering High-Level Scoped Variables

  The Decompiler understands how compilers use processor stacks and registers to implement variables with different scopes within a function. Data-flow analysis allows it to follow what was originally a single variable as it moves from the stack, into a register, into a different register, etc. Thus it can effectively recover the original program's concept of a variable, minimizing the need to introduce artificial variables in the output.

Recovering Function Parameters

  The Decompiler understands the parameter-passing conventions of the compiler and can reconstruct the original form of function calls.

Using Data-type, Name, and Signature Annotations

  The Decompiler automatically pulls in all the different data types and variable names that the user has applied to functions, and the C output is altered to reflect this. High-level variables are appropriately named, structure fields and array indices are calculated and displayed with correct syntax, constant char pointers are replaced with appropriate quoted strings, etc.

Propagating Local Data-types

  The Decompiler infers the data-type of unlabeled variables by propagating information from other sources throughout a function.

Recovering Structure Definitions

  The Decompiler can be used to create structures that match the usage pattern of particular functions and variables, automatically discovering component offsets and data-types.

## Decompiler Concepts

### P-code

P-code is Ghidra's Intermediate Representation (IR) language. When analyzing a function, the Decompiler translates every machine instruction into p-code first and performs its analysis directly on the operators and variables of the language. Output of the Decompiler is also best understood in terms of p-code. This section presents the key concepts of p-code. For a more detailed discussion see the document "P-Code Reference Manual."

#### Address Space

P-code defines all data in terms of an address space. An address space is defined simply as an indexed sequence of bytes that can be read and written by p-code operations. For a specific byte, the unique index that labels it is called the byte's address. Each address space has a:

- name - a formal name for the space
- size - the maximum number of bytes that can be addressed
- endianness - how groups of bytes are interpreted as integers

For a p-code model of a specific processor, all elements of the processor state (including RAM, registers, flags, etc.) must be contained in some address space. The model will define multiple address spaces to accomplish this, and beyond the raw translation of machine instructions to p-code, the Decompiler can add additional spaces. Address space definitions that are common across many different processors include:

ram

  A space that models memory accessible via the processor's main data bus. Depending on the architecture, different spaces might be substituted for ram, such as separate code and data spaces.

register

  A space that models the processor's general purpose registers. Ghidra still uses the standard names to refer to registers for the processor, but internally each register maps to a specific address in this space.

unique

  A space dedicated to temporary registers. It is used to hold intermediate values when modeling instruction behavior, and the Decompiler uses it to allocate space for variables that don't directly correspond to the low level processor state. The name unique is reserved for this purpose and is present in all processor models.

stack

  A space that represents bytes explicitly indexed through a stack pointer. This is an example of an address space added by the Decompiler beyond what the raw processor model defines. The stack space is a logical construction representing the set of bytes a single function might access through its stack pointer. Each stack address represents the offset of a byte in some underlying space (usually ram) relative to the initial value of the stack pointer upon entry to the function. The stack space is always referenced in the context of a single function, and in this sense, each function can be viewed as having its own distinct stack space.

constant

  A special space for encoding constants in p-code. For complete generality, even constants that the processor might manipulate are assigned to their own address space. For an address in the constant space, the index itself represents the constant.

#### Varnodes

A varnode is defined as a sequence of bytes in an address space. It represents the storage for a single value (variable) being acted on by the processor. All manipulation of data by p-code operations occurs on varnodes. A varnode can always be represented as the formal triple:

`(address space,offset,size)`
Both offset and size are integer values specified in terms of bytes. The first two elements, address space and offset, taken together represent the address of the varnode.

Varnodes by themselves do not necessarily have a data-type associated with them. The Decompiler ultimately assigns a formal data-type, but at the lowest level of p-code, varnodes inherit one the building block data-types from the p-code operations that act on them:

- Integer
- Boolean
- Floating Point

The integer data-type assumes a two's complement encoding in the endianness of the address space containing the varnode. Similarly, the floating point data-type assumes an IEEE 754 standard encoding. The precision of the integer or floating point value is determined by the varnode's size. A boolean data-type assumes the varnode has a size of 1 byte and takes either a value of 0, for false, or a value of 1 for true.

#### P-code Operations

A p-code operation is defined as a formal operator, labeled by its opcode, acting on 1 or more varnodes as input and storing a result in at most 1 varnode. Each p-code operation is associated with an address, which is usually the address of the machine instruction from which the p-code operation was translated. As most instructions require more than one p-code operation to fully model it, a separate 1-up counter is used to distinguish p-code operations associated with the same address. Together the address and the counter are referred to as the operation's sequence number.

The formal opcodes break up into categories similar to many programming languages.

P-code Operations
Category | Operations
Data Moving | `COPY, LOAD, STORE`
Integer Arithmetic | `INT_ADD, INT_SUB, INT_2COMP, INT_MULT, INT_DIV, INT_SDIV, INT_REM, INT_SREM`
Integer Shifts | `INT_LEFT, INT_RIGHT, INT_SRIGHT`
Integer Comparison | `INT_EQUAL, INT_NOTEQUAL, INT_SLESS, INT_SLESSEQUAL, INT_LESS, INT_LESSEQUAL`
Logical | `INT_NEGATE, INT_XOR, INT_AND, INT_OR, POPCOUNT`
Boolean | `BOOL_NEGATE, BOOL_XOR, BOOL_AND, BOOL_OR`
Floating Point Arithmetic | `FLOAT_ADD, FLOAT_SUB, FLOAT_MULT, FLOAT_DIV, FLOAT_NEG, FLOAT_ABS, FLOAT_SQRT`
Floating Point Comparison | `FLOAT_EQUAL, FLOAT_NOTEQUAL, FLOAT_LESS, FLOAT_LESSEQUAL`
Floating Point Conversion | `INT2FLOAT, FLOAT2FLOAT, TRUNC, CEIL, FLOOR, ROUND`
Branching | `BRANCH, CBRANCH, BRANCHIND, CALL, CALLIND, RETURN`
Extension/Truncation | `INT_ZEXT, INT_SEXT, PIECE, SUBPIECE`
Overflow Tests | `INT_CARRY, INT_SCARRY, INT_SBORROW, FLOAT_NAN`
Managed Code | `CPOOLREF, NEW`

##### Operator Tokens

Most opcodes naturally correspond to a particular C operator token, and in Decompiler output, many of the operator tokens displayed correspond directly to a p-code operation present in the Decompiler's internal representation. The biggest exception are the Branching operations; the Decompiler uses standard high-level language control-flow structures, like if/else, switch, and do/while blocks, instead of the low-level branching operations. But even here, there is some correspondence between operations and keywords in the high-level language.

Operations in the Extension/Truncation and Floating Point Conversion categories tend to be represented as cast operations in the high-level language, and so don't have an explicit operator token representing them. Many p-code operations share the same operator token, such as the integer and floating-point addition operations INT_ADD and FLOAT_ADD. The high-level language distinguishes between them via the underlying data-type of the variables.

Name | Operator Token | Description
COPY | `=` | Copy one varnode into another.
LOAD | `*` or `->` | Dereference a pointer, or load a value from memory.
STORE | `*` or `->` | Store a value to memory, through a pointer.
BRANCH | `goto` | Branch execution to a specific address.
CBRANCH | `if (...) goto` | Branch execution to an address if the condition is true.
BRANCHIND | `switch(...)` | Branch execution to a computed address.
CALL | `funcname(...)` | Branch to a function, as a call.
CALLIND | `(*funcptr)(...)` | Branch through a pointer to a function, as a call.
RETURN | `return` | Return execution to the calling function.
PIECE | `CONCAT` | Concatenate two varnodes.
SUBPIECE | `SUB` | Extract a subset of bytes.
POPCOUNT | `POPCOUNT` | Count the 1 bits.
INT_EQUAL | `==` | True if input varnodes are equal.
INT_NOTEQUAL | `!=` | True if input varnodes are not equal.
INT_LESS | `<` or `>` | True if one varnode is less than the other as unsigned integers.
INT_SLESS | `<` or `>` | True if one varnode is less than the other as signed integers.
INT_LESSEQUAL | `<=` or `>=` | True if one varnode is less than or equal to the other as unsigned integers.
INT_SLESSEQUAL | `<=` or `>=` | True if one varnode is less than or equal to the other as signed integers.
INT_ZEXT | `ZEXT` | Zero extension.
INT_SEXT | `SEXT` | Signed extension.
INT_ADD | `+` | Add as integers.
INT_SUB | `-` | Subtract as integers.
INT_CARRY | `CARRY` | True if adding produces an unsigned carry.
INT_SCARRY | `SCARRY` | True if adding produces a signed carry.
INT_SBORROW | `SBORROW` | True if subtracting produces a signed borrow.
INT_2COMP | `-` | Two's complement.
INT_NEGATE | `~` | Bitwise negation.
INT_XOR | `^` | Bitwise exclusive-or.
INT_AND | `&` | Bitwise logical-and.
INT_OR | `|` | Bitwise logical-or.
INT_LEFT | `<<` | Left shift.
INT_RIGHT | `>>` | Unsigned (logical) right shift.
INT_SRIGHT | `>>` | Signed (arithmetic) right shift.
INT_MULT | `*` | Integer multiplication.
INT_DIV | `/` | Unsigned integer division.
INT_REM | `%` | Unsigned remainder.
INT_SDIV | `/` | Signed division.
INT_SREM | `%` | Signed remainder.
BOOL_NEGATE | `!` | Boolean negation.
BOOL_XOR | `^^` | Boolean exclusive-or.
BOOL_AND | `&&` | Boolean logical-and.
BOOL_OR | `||` | Boolean logical-or.
FLOAT_EQUAL | `==` | True if inputs are equal as floating-point numbers.
FLOAT_NOTEQUAL | `!=` | True if inputs are not equal as floating-point numbers.
FLOAT_LESS | `<` or `>` | True if one input is less than the other as floating-point numbers.
FLOAT_LESSEQUAL | `<=` or `>=` | True if one input is less than or equal to the other as floating-point numbers.
FLOAT_ADD | `+` | Add as floating-point numbers.
FLOAT_SUB | `-` | Subtract as floating-point numbers.
FLOAT_MULT | `*` | Multiply as floating-point numbers.
FLOAT_DIV | `/` | Divide as floating-point numbers.
FLOAT_NEG | `-` | Negate a floating-point number.
FLOAT_ABS | `ABS` | Absolute value of a floating-point number.
FLOAT_SQRT | `SQRT` | Square root of a floating-point number.
FLOAT_CEIL | `CEIL` | Ceiling function.
FLOAT_FLOOR | `FLOOR` | Floor function.
FLOAT_ROUND | `ROUND` | Nearest integral value.
FLOAT_NAN | `NAN` | True if input is not a valid floating-point number (NaN).
INT2FLOAT | `<na>` | Convert integer to floating-point.
FLOAT2FLOAT | `<na>` | Convert between different floating-point precisions.
TRUNC | `<na>` | Convert floating-point to integer.
CPOOLREF | `<na>` | Obtain constant pool value.
NEW | `new` | Allocate an object or an array of objects.
MULTIEQUAL | `<na>` | Compiler phi-node: merge values from multiple control-flow paths.
INDIRECT | `<na>` | Indirect effect on a varnode.
CAST | `<na>` | Copy a value, changing its data-type.
PTRADD | `+` | Add an offset to a pointer.
PTRSUB | `.` or `->` | Dereference a subfield from a pointer.
INSERT | `<na>` | Insert a bit-range.
EXTRACT | `<na>` | Extract a bit-range.

##### P-code Control Flow

P-code has natural control flow, with the subtlety that flow happens both within and across machine instructions. Most p-code operators have fall-through semantics, meaning that flow moves to the next operator in the sequence associated with the instruction, or, if the operator is the last in the sequence, flow moves to the first operator in the p-code associated with the next instruction. The p-code operators with branching semantics, such as CBRANCH and BRANCH, can jump to a target operator which is internal to the current instruction, or they can jump to the first p-code operator corresponding to a new instruction at a different address.

Ghidra labels a machine instruction with one of the following Flow Types that describe its overall control flow. The Flow Type is derived directly from the control flow of the p-code for the instruction, with the basic types corresponding directly with a specific branching p-code operator.

- FALL_THROUGH
- UNCONDITIONAL_CALL - CALL
- UNCONDITIONAL_JUMP - BRANCH
- CONDITIONAL_JUMP - CBRANCH
- COMPUTED_JUMP - BRANCHIND
- COMPUTED_CALL - CALLIND
- TERMINATOR - RETURN

Other Flow Types occur due to a combination of multiple p-code branching operators within the same instruction.

- CONDITIONAL_CALL - CALL with CBRANCH
- CONDITIONAL_TERMINATOR - RETURN with CBRANCH
- COMPUTED_CALL_TERMINATOR - CALLIND with RETURN
- CONDITIONAL_COMPUTED_JUMP - CBRANCH with BRANCHIND
- CONDITIONAL_COMPUTED_CALL - CBRANCH with CALLIND
- JUMP_TERMINATOR - BRANCH with RETURN

##### User-defined P-code Operations - CALLOTHER

P-code allows for additional, processor specific, operations referred to as user-defined or CALLOTHER operations. These may be defined as part of a Ghidra's specification for the processor and are typically used as placeholders for what is otherwise unmodeled processor behavior. Each CALLOTHER must have a unique name, and as a p-code operation, it still takes varnode inputs and may produce a varnode output. But the exact affect of the operation is not specified.

The Decompiler treats a CALLOTHER operation as a black box. It will keep track of data flowing into and out of the operation but won't simplify or transform it. In Decompiler output, a CALLOTHER is usually displayed using its unique name, with functional syntax showing its inputs and output.

Ghidra or a user can provide the behavior details for a named CALLOTHER operation. The details are provided as a sequence of p-code operations, referred to as a Callother-Fixup, which is substituted for the CALLOTHER operation during decompilation, or by other Analyzers that use p-code. Callother-Fixups are applied by Ghidra for specific processor or compiler variants, and a user can choose to apply them to an individual Program (see ).

##### Internal Decompiler Functions

Certain p-code operations can show up in Decompiler output that cannot be represented as either an operator token, a cast operation, or other depiction that is natural to the language. The Decompiler generally tries to eliminate these, but this isn't always possible. The Decompiler resorts to a functional syntax for these kinds of p-code operations, displaying them as if they were built-in functions for the language.

`SUB41(x,c)` - Truncation operation - SUBPIECE
  - The digit '4' indicates the size of the input operand 'x' in bytes.
  - The digit '1' indicates the size of the output value in bytes.
  - The parameter 'x' is the value being truncated.
  - The parameter 'c' is the number of least significant bytes being truncated.

      	    SUB42(0xaabbccdd,1) = 0xbbcc

  Extract a contiguous subset of the bytes from 'x'. When 'c' is 0, the operation is a simple integer truncation.

  - `SUB41(x,0)` truncates from a 4-byte integer to a 1-byte (char or byte) integer.
  - `SUB42(x,0)` truncates from a 4-byte integer to a 2-byte (short) integer.
  - `SUB84(x,4)` extracts the high 4 bytes from the 8 byte integer.
`CONCAT31(x,y)` - Concatenation operator - PIECE
  - The digit '3' indicates the size of the input operand 'x' in bytes.
  - The digit '1' indicates the size of the input operand 'y' in bytes.
  - The parameters 'x' and 'y' hold the values being concatenated.

      	    CONCAT31(0xaabbcc,0xdd) = 0xaabbccdd

  Concatenate the bytes in 'x' with the bytes in 'y'. 'x' becomes the most significant bytes, and 'y' the least significant bytes, in the result.

`ZEXT14(x)` - Zero-extension operator - INT_ZEXT
  - The digit '1' indicates the size of the input operand 'x' in bytes.
  - The digit '4' indicates the size of the output in bytes.

      	    ZEXT24(0xaabb) = 0x0000aabb

  Extend the operand 'x' to a larger size by appending zero bytes, which become the most significant bytes of the result.

`SEXT14(x)` - Sign-extension operator - INT_SEXT
  - The digit '1' indicates the size of the input operand 'x' in bytes.
  - The digit '4' indicates the size of the output in bytes.

      	    SEXT48(0xaabbccdd) = 0xffffffffaabbccdd

  Extend the operand 'x' to a larger size by duplicating the sign bit of 'x' into the most significant bytes of the result.

`SBORROW4(x,y)` - Test for signed borrow operator - INT_SBORROW
  - The digit '4' indicates the size of both input operands 'x' and 'y' in bytes.

  Return true if there is an arithmetic overflow when subtracting 'y' from 'x' as signed integers.

`CARRY4(x,y)` - Test for unsigned overflow operator - INT_CARRY
  - The digit '4' indicates the size of both input operands 'x' and 'y' in bytes.

  Return true if there is an arithmetic overflow when adding 'x' and 'y' as unsigned integers.

`SCARRY4(x,y)` - Test for signed overflow operator - INT_SCARRY
  - The digit '4' indicates the size of both input operands 'x' and 'y' in bytes.

  Return true if there is an arithmetic overflow when adding 'x' and 'y' as signed integers.

### The HighFunction

A HighFunction is the collection of specific information produced by the Decompiler about a function, referring to the root class in the Ghidra source which holds this information. The HighFunction is made up of the following explicit objects:

- A control-flow representation of the function in terms of basic blocks.
- A data-flow representation of the function in terms of varnodes and p-code operations.
- A symbol-table of variables accessed by the function.

The Decompiler's output provides a standalone view of the function which is distinct from any annotations about the function that are present in the Program database and displayed in the Listing (although the output may be informed by these annotations). The terms HighFunction, HighVariable, and HighSymbol refer to this Decompiler specific view of the function.

#### HighSymbol

A HighSymbol is one of the explicit symbols recovered by the Decompiler. It is made up of a name and data-type and can describe either:

- a formal parameter of the function,
- a local variable of the function, or
- a global variable accessed by the function.

An important aspect of HighSymbols is that they are distinct from the standard Ghidra symbols stored in the Program database and are part of the Decompiler's separate view of the function. When the Decompiler displays declarations for symbols in its output for instance, it is displaying HighSymbols, which may not directly match up with database symbols. The Decompiler is generally informed by annotations in the database and may copy specific symbols from the database into its view, but it is generally free to invent new symbols discovered during its analysis.

Various actions within Ghidra allow the user to commit specific HighSymbols to the database as a permanent annotation, but this does not happen by default.

#### Varnodes in the Decompiler

Varnodes are the central variable concept for the Decompiler. They form the individual nodes in the Decompiler's data-flow representation of functions and are used during all stages of analysis. During the initial stages of analysis, varnodes simply represent specific storage locations that are accessed in sequence by individual p-code operations. The Decompiler immediately converts the p-code into a graph-based data-flow representation, called Static Single Assignment (SSA) form. In this form, the varnodes take on some additional attributes.

In SSA form, each write of an operation to a storage location defines a new varnode. Write operations at different points in the code to the same storage location, still produce different varnodes. In this context, each varnode has a lifetime or scope within the function. The scope starts at:

- The defining p-code operation which has the varnode as its output. Or

- The beginning of the function, if the varnode is an input to the function.

The scope extends via control flow to each p-code operation that reads the specific varnode as an operand. The value of the varnode between the defining p-code operation and the reading operations does not change. The scope of a varnode can be thought of as a set of addresses within the function's body connected by control flow. The address of the defining p-code operation is referred to as the varnode's first use point or first use offset.

In the Decompiler output for a specific high-level language like C or Java, a varnode still has a scope and represents a variable in the high-level language only across this connected region of the code. A set of varnodes, with disjoint scopes, provides a complete description of a high-level variable that can be written to at more than one point in the function.

#### HighVariable

A HighVariable is a set varnodes that, taken together, represent the storage of an entire variable in the high-level language being output by the Decompiler. Each varnode describes where the variable's value is stored across some section of code.

There is generally a one-to-one correspondence between HighVariables and HighSymbols. HighVariables can be thought of as the detailed storage description of the high-level variable, while the HighSymbol provides its name and data-type. However, there are some technical caveats to this correspondence to keep in mind.

A HighVariable always describes explicit manipulation of data by instructions in the function. In some cases, a HighVariable may only describe part of the storage for a HighSymbol. Particularly for structured or composite data-types, a function may operate on different parts of the variable at different points of the code, so a HighVariable may only encompass one field of the structure.

A symbol may be referenced in a function, but the symbol's value may not be explicitly manipulated. Constant pointers may refer to variables either on the stack or in main memory, but the variable's value is neither read nor written within the function. In this case, the HighSymbol exists, but there is no corresponding HighVariable.

##### Merging

Merging is the part of the analysis process where the Decompiler decides what varnodes get grouped together to create the final HighVariables in the output. Each varnode's scope (see the discussion in ) provides the fundamental restriction on this process. Two varnodes cannot be merged if their scopes intersect. But this leaves a lot of leeway in what varnodes can be merged.

Certain varnodes must be merged; if they use the same storage but in different control-flow paths that come together, for instance, or if it is explicitly known that the varnodes must represent the same variable. This is referred to as forced merging.

The Decompiler may also merge varnodes that could just as easily exist as separate variables. This is called speculative merging. In addition to the intersection condition on varnode scopes, the Decompiler only speculatively merges variables that share the same data-type. Beyond this, the Decompiler prioritizes variable pairs that are read and written within the same instruction and then pairs that are near each other in the control flow of the function. To a limited extent, users are able to control this kind of merging (see ).

#### Prototype Model

Functions in high-level languages manipulate symbols like parameters and return values that are implicitly stored in a way that doesn't collide with other functions and variables. To actually map these symbols to physical registers and memory locations, compilers establish a calling convention for the function. Loosely, this is a set of memory resources, whether it is registers or stack locations, and a procedure for sequentially assigning resources to parameters based on their properties. A prototype model is the formal object in Ghidra that represents a calling convention and holds its specific rules and resource details.

Prototype models are architecture-specific, and depending on the compiler, a single Program may make use of multiple models. Subsequently, each distinct model has a name like __stdcall or __thiscall. The Decompiler makes use of the prototype model, as assigned to the function by the user or discovered in some other way, when performing its analysis of parameters. It is possible for users to extend the set of prototype models available to a Program (see ).

A prototype model is typically used as a whole and is assigned by name to individual functions. But some of the sub-concepts of the model may be relevant to reverse engineers. Concepts that a prototype model encapsulates include:

##### Incoming and Outgoing Storage Locations

A formal input parameter is always assigned a specific memory location to hold its value coming into the function. The storage location can be a register, a stack location, or other memory location. The storage location may be reused later by other variables in the function; only the incoming value stored there is guaranteed to be that of input parameter.

If the parameter is stored on the stack, the storage location is viewed as a constant offset in the stack space, where the offset is relative to the incoming value of stack pointer (see the discussion in ).

The return value for the function, unless it is passed back on the stack, is also stored at a single memory location. It is guaranteed to be at that location only at points where the function is exited. There may be multiple exit points, but they all share the same return value storage location. For return values passed back on the stack, compilers generally implement a special input register to hold the location where the value will be stored. See the discussion of and the __return_storage_ptr__ below.

##### Auto-Parameters

Compiled binaries may pass values as parameters between functions that aren't in the formal list of parameters as defined by the original source code for the program. These are referred to as auto-parameters or sometimes hidden parameters within the documentation. If the prototype model requires it, Ghidra will automatically create an auto-parameter for a function to honor a user's request for a specific formal signature. See Function Editor Dialog. Because reverse engineers need to see them, the Decompiler will generally display auto-parameters explicitly in function prototypes as part of its output, even though they would not be present in the original source. Ghidra explicitly defines two auto-parameters:

this

  Within Object Oriented languages, a function defined as a class method often has a this parameter pointing to an instantiation of the class' structure data-type. Within Ghidra, functions with the __thiscall calling convention are automatically assigned a this parameter. If the function is part of a class namespace and the class has an associated structure, the this parameter will be a pointer to the structure, otherwise it will be a pointer to the void data-type.

__return_storage_ptr__

  Most calling conventions allow the value returned by a function, if it is large enough, to be passed back on the stack instead of in a register. This is usually implemented by having the calling function pass an additional input parameter that holds a pointer to the location on the stack where the return value should be stored. Ghidra labels this special parameter as __return_storage_ptr__, which will be a pointer to the data-type of the return value.

##### Unaffected

Prototype models can specify a set of unaffected memory locations, whose value must be preserved across the function. I.e. each location must hold the same value at a function's exit that it held coming into the function. These encompass a calling convention's saved registers, where a calling function can store values it doesn't want to change unexpectedly, but also may include other registers that are known not to change, like the stack pointer. The Decompiler uses the information to determine which locations can be safely propagated across a called function.

##### Killed by Call

In contrast to unaffected memory locations, a prototype model may specify killed by call locations that are guaranteed not to be used to hold a value across the function.

### SLEIGH Specification Files

SLEIGH is Ghidra's specification language for describing processor instructions. Specification files are read in for a Program, and once configured, Ghidra's SLEIGH engine can:

- Disassemble machine instructions from the underlying bytes and
- Produce the raw p-code consumed by the Decompiler and other analyzers.

Specification files are selected based on the Language Id assigned to the Program at the time it is imported into Ghidra (see Import Program).

- `x86:LE:32:default:windows`
- `AARCH64:LE:64:default:v8A:default`
- `MIPS:BE:32:micro:default`

A Language Id is a label with these 5 formal fields, separated by a ':' character:

- Processor family
- Endianness
- Size of the address bus
- Processor variant
- Compiler producing the Program

A field with the value default indicates either the preferred processor variant or the preferred compiler.

Within the Ghidra installation, specification files are stored based on the overarching processor family, such as MIPS or x86. For a specific family, files are located under

`<Root>/Ghidra/Processors/<Family>/data/languages`
where `<Root>` represents the root directory of the Ghidra installation and `<Family>` is the processor family.

There are several types of specification files that are distinguishable by their suffix. These include:

SLEIGH files - *.slaspec or *.sinc

  These are the human readable SLEIGH language files. A single specification is rooted in one of the `*.slaspec` files, which may recursively include one or more `*.sinc` files. The format of these files is described in the document "SLEIGH: A Language for Rapid Processor Specification."

Compiled SLEIGH files - *.sla

  This is a compiled form of a single SLEIGH specification. It is produced automatically by Ghidra from the corresponding `*.slaspec`.

Compiler specification files - *.cspec

  These files contain configuration for a specific compiler. Analysis of Programs whose executable content was produced using this compiler benefits from this information. The file is an XML document with tags describing details of data organization and other conventions used by the compiler. In particular, the compiler specification contains tags:

  - <prototype> - describing a specific calling convention
  - <callfixup> - describing a Call-fixup
  - <callotherfixup> - describing a Callother-fixup
Processor specification files - *.pspec

  These files contain configuration information that is specific to a particular processor variant.

#### Modifying Specification Files

Changing any of the specification files described here is not recommended. To make additions to either the compiler specification or the processor specification files, see , which describes a safe and portable way to add specific elements.

Making modifications to specification files within a Ghidra installation is possible, but any analysis results obtained will likely not be portable to other installations. In particular, saving a Program from a modified Ghidra and then reopening it using an unmodified installation may corrupt the Program database.

When Ghidra starts, it checks for changes to `*.slaspec` and `*.sinc` files and will rebuild the corresponding `*.sla` file automatically. Also, specification files are read again when Ghidra restarts. So analysts can and do make changes to these files. However they need to be prepared to view any results as temporary and should backup their installation and specific Programs being analyzed.

## Program Annotations Affecting the Decompiler

### Machine Instructions

Individual machine instructions make up the biggest source of information when the Decompiler analyzes a function. Instructions are translated from their processor-specific form into Ghidra's IR language (see ), which provides both the control-flow behavior of the instruction and the detailed semantics describing how the processor and memory state are affected. The translation is controlled by the underlying processor model and, except in limited circumstances, cannot be directly altered from the tool. Flow Overrides (see below) can change how certain control flow is translated and, depending on the processor, how context registers affect p-code (see ).

Outside of the tool, users can modify the model specification itself. See the document "SLEIGH: A Language for Rapid Processor Specification."

Decompiling a function starts by analyzing the control flow of machine instructions. Control flow is traced from the first instruction, through additional instructions depending on their flow semantics (see ). All paths are traced through instructions with any form of fall-through or jump semantics until an instruction with terminator semantics is reached, which is usually a formal return (return from subroutine) instruction. Flow is not traced into called functions, in this situation. Instructions with call semantics are treated only as if they fall through.

An entry point is the address of the instruction first executed when the function is called.

A function body is the set of addresses reached by control-flow analysis and the machine instructions at those addresses.

#### Entry Point

The entry point address for a function plays a pivotal role for analysis using the Decompiler. Ghidra generally associates a formal Function Symbol and an underlying Function object at this address, which are the key elements that need to be present to trigger decompilation (see Functions). The Function object stores the function body, parameters, local variables, and other information critical to the decompilation process.

Function Symbols and Function objects are generally created automatically by a Ghidra analyzer when initially importing a binary executable and running Auto Analysis. If necessary, however, a user can manually create a Function object from a Listing window by using the Create Function command (pressing the 'F' key), when the cursor is placed on the function's entry point (see Create Function).

#### Formal Function Body

When a function is created, Ghidra stores its function body as a set of addresses in the Program database. This formal function body delineates the function from all the other kinds of data within the Program and lets Ghidra immediately link addresses in the middle of the function to the entry point and the Function object. Decompiler windows in particular use the formal function body to know which function to decompile in response to a navigation event to an arbitrary address.

The Decompiler does not use the formal function body when it computes control flow; it recomputes its own idea of the function body starting from the entry point it is handed. If the formal function body was created manually, using a selection for instance, or in other extreme circumstances, the Decompiler's view of the function body may not match the formal view. This can lead to confusing behavior, where clicking in a Decompiler window may unexpectedly navigate the window away from the function.

#### Flow Overrides

Control-flow behavior for a machine instruction is generally determined by its underlying p-code (see ), but this can be changed by applying a Flow Override. A Flow Override maintains the overall semantics of a branching instruction but changes how the branch is interpreted. For instance, a `JMP` instruction, which traditionally represents a branch within a single function, can be overridden to represent a call to a new function. Flow Overrides are applied by Analyzers or manually by the user.

The Decompiler automatically incorporates any relevant Flow Overrides into its analysis of a function. This can have a significant impact on results. The types of possible Flow Overrides include:

BRANCH Override

  Treats the primary CALL or RETURN behavior of the instruction as if it were a BRANCH within the function. For CALL instructions, the call target becomes the branch destination, and the instruction is no longer assumed to fall through. RETURN instructions become an indirect branch, and the Decompiler will attempt to recover branch destinations using switch analysis.

CALL Override

  Treats the primary BRANCH or RETURN behavior of the instruction as if it were a CALL. A BRANCH becomes a fall through instruction, and the destination address becomes the call target, which may no longer be considered part of the function. The computed address for an indirect BRANCH or RETURN instruction becomes the target address of an indirect CALL.

CALL_RETURN Override

  Treats the primary BRANCH or RETURN behavior of the instruction as if it executed a CALL followed by a RETURN operation. The destination address of a BRANCH becomes the call target, which may no longer be considered part of the function. The computed address for an indirect BRANCH or RETURN instruction becomes the target address of an indirect CALL.

RETURN Override

  Treats an indirect BRANCH or CALL instruction as if it were a RETURN instruction, terminating the control-flow path within the function. The computed destination address is considered part of the return mechanism of the function and may no longer be explicitly displayed in the output. An indirect BRANCH no longer invokes switch analysis during decompilation.

### Comments

The Decompiler automatically incorporates comments from the Program database into its output. Comments in Ghidra are centralized and can be created and displayed by multiple Program views, including the Decompiler. Comments created from a Decompiler window will show up in a Listing window for instance, and vice versa.

For the purposes of understanding comments within the Decompiler, keep in mind that:

- An individual comment is associated with a specific address in the Program.
- There are 5 different types of comments:
  - Plate
  - Pre
  - Post
  - End-of-line (EOL)
  - Repeatable

For general documentation on creating and editing comments within Ghidra, see Comments.

#### Display

The Decompiler collects and displays comments associated with any address in the formal function body currently decompiling. The comments are integrated line by line into the decompiled code, and an individual comment is displayed on the line before the line of code incorporating the instruction associated with the comment's address.

Because a single line of code typically encompasses multiple machine instructions, there is a possibility that multiple comments at different addresses apply to the same line. In this case, the Decompiler displays each comment on its own line, in address order, directly before the line of code.

Because the output of the Decompiler can be a heavily transformed version compared to the original machine instructions, it is possible that individual instructions no longer have explicit tokens representing them in the output. Comments attached to these instruction will still be displayed in the Decompiler output with the closest associated line of code, usually within the same basic block.

By default, the Decompiler displays only the Pre comments within the body of the function. It also displays Plate comments, but only if they are attached to the entry point of the function. In this case, they are displayed first in the Decompiler output, along with WARNING comments, before the function declaration. Other comment types can be configured to be part of Decompiler output by changing the Decompiler display options (see ).

Unlike a Listing window, the Decompiler does not alter how a comment is displayed based on its type. All enabled types of comment are displayed in the same way, on a separate line before the line of code associated with the address.

#### Unreachable Blocks

The Decompiler may decide as part of its analysis that individual basic blocks are unreachable and not display them in the output. In this case, any comments associated with addresses in the unreachable block will also not be displayed.

#### Warning Comments

The Decompiler can generate internal warnings during its analysis and will incorporate them into the output as comments in the same way as the user-defined comments described above. They are not part of Ghidra's comment system, however, and cannot be edited. They can be distinguished from normal comments by the word 'WARNING' at the beginning of the comment.

`/* WARNING: ... */`

### Variable Annotations

Variable annotations are the most important way to get names and data-types that are meaningful to the user incorporated into the Decompiler's output. A variable in this context is loosely defined as any piece of memory that code in the Program treats as a logical entity. The Decompiler works to incorporate all forms of annotation into its output for any variable pertinent to the function being analyzed.

At a minimum, a variable annotation in Ghidra provides a:

- Symbol name,
- Data-type, and
- Storage location.

#### Creating Variable Annotations

Ghidra provides various ways that a name and other attributes can be ascribed to a variable. These break up roughly into global variables, defined directly on memory in the Program image, and variables that are local to a function.

Global variable annotations are created from the tool by applying a data-type to a memory location in a Listing window, either by invoking a command from the Data pop-up menu or by dragging a data-type from the Data Type Manager window directly onto the memory location. Refer to the documentation:

- Applying Data Type

Local variables annotations are created from the Listing using various editor dialogs. See, in particular:

- Function Signature Dialog
- Stack Frame Editor
- Creating a Default Reference

The Decompiler window also provides numerous ways of annotating variables, both local and global. In particular, see the commands:

#### Variable Symbols

Ghidra maintains its own symbol table that supports namespaces and function scopes, and variable names are automatically incorporated into this. In order to widely accommodate different use cases, Ghidra's symbol table has extremely lax naming rules. Ghidra may allow names that conflict with the stricter rules of the language the Decompiler is attempting to produce. The Decompiler does not currently have an option that checks for this. Users should be aware of:

Illegal Characters

  Ghidra symbols allow almost every printable character except a space in a symbol name; punctuation and keywords can be incorporated.

Duplicate Symbols

  Ghidra allows different functions to have the same name, even within the same namespace, in order to model languages that support function overloading. In most languages, such functions would be expected to have distinct prototypes to allow the symbols to be distinguished in context. Ghidra and the Decompiler, however, do not check for this, as prototypes may not be known.

##### Variable Scope

All variables belong to either a global or local scope, which directly affects how the variable is treated in the Decompiler's data-flow analysis. Annotations created by applying a data-type directly to a memory location in the Listing are automatically added to the formal global namespace. Ghidra can create other custom namespaces that are considered global in this sense, and renaming actions provide options that let individual global annotations be moved into these namespaces. Dialogs that are brought up in the context of a function, like the Function Signature Editor, create variable annotations that are local to that function.

A global variable annotation forces the Decompiler to treat the memory location as if its value persists beyond the end of the function. The variable must exist at all points of the function body, generally at the same memory location.

Local variables, in contrast, do not generally exist across the whole function, but come into scope at the instruction that first writes to them, and then exist only up to the last instruction that reads them. The memory location storing a local variable at one point of the function may be reused for different variables at other points. This can cause ambiguity in how the Decompiler should treat a given memory location used for storing local variables, which the user may want to steer. See the discussion in .

#### Variable Data-types

Ghidra provides extensive support for naming and describing data-types that are tailored for the Program being analyzed. Data-types that are explicitly part of a variable annotation are, to the extent possible, automatically incorporated into the Decompiler's analysis.

##### Data-types Supported by the Decompiler

The Decompiler understands traditional primitive data-types in all their various sizes, like integers, floating-point numbers, booleans, and characters. It also understands pointers, structures, and arrays, letting it support arbitrarily complicated composite data-types. Ghidra provides some data-types with specialized display capabilities that don't have a natural representation in the high-level language output by the Decompiler. The Decompiler treats these as black-box data-types, preserving the name, but treating the underlying data either as an integer or simply as an array of bytes.

###### Undefined

The undefined data-types are supported in their various sizes: undefined1, undefined2, undefined4, etc. In Ghidra, the undefined data-types let the user specify the size of a variable, while formally declaring that other details about the data-type are unknown.

For the Decompiler, undefined data-types, as an annotation, have the important special meaning that the Decompiler should let its analysis determine the final data-type presented in the output for the variable (see below).

###### Void

The void data-type is supported but treated specially by the Decompiler, as does Ghidra in general. A void can be used to indicate the absence of a return value in function prototypes, but cannot be used as a general annotation on variables. A void pointer, void *, is possible; the Decompiler treats it as a pointer to an unknown data-type.

###### Integer

Integer data-types, both signed and unsigned, are supported up to a size of 8 bytes. Larger sizes are supported internally but are generally represented as an array of bytes in Decompiler output. Nonstandard integer sizes of 3, 5, 6, and 7 bytes are also supported.

The standard C data-type names: int, short, long, and long long are mapped to specific sizes based on the processor and compiler selected when importing the Program.

###### Boolean

A 1-byte boolean data-type is supported. Boolean constants are rendered as either the token true or the token false.

###### Floating-point

Floating-point sizes of 4, 8, 10, and 16 are supported, mapping in all cases currently to the float, double, float10, and float16 data-types, respectively. The Decompiler currently cannot display floating-point constants that are bigger than 8 bytes.

###### Character

ASCII- and Unicode-encoded character data-types are supported for sizes of 1, 2, and 4. The size effectively chooses between the UTF8, UTF16, and UTF32 character encodings, respectively. The standard C data-type names char and wchar_t are mapped to one of these sizes based on the processor and compiler selected when importing the Program.

###### String

Terminated strings, encoded either in ASCII or Unicode, are supported. The Decompiler converts Ghidra's dedicated string data-types like string to an array-of-characters data-type, such as char[], where the character size matches the encoding. A pointer-to-character data-type like

- `char *` or
- `wchar_t *`

is also treated as a potential string reference. The Decompiler can infer terminated strings if this kind of data-type propagates to constant values during its analysis.

Strings should be fully rendered in Decompiler output, with non-printable characters escaped using either traditional sequences like '\r', '\n' or using Unicode escape sequences like '\xFF'.

###### Pointer

Pointer data-types are fully supported. A pointer to any other supported data-type is possible. The data-type being pointed to, whether it is a primitive, structure, or another pointer, informs how the Decompiler renders a dereferenced pointer or other pointer expression.

The Decompiler automatically assumes that a pointer may reference an array of the underlying data-type. If an integer value is added to the pointer and the value is known to be a multiple of the data-type's size, the expression is treated as either pointer arithmetic or as an array access, and the multiplication factor is hidden. Adding smaller integers to a structure pointer typically results in a field access expression using the '->' or other language specific token. See the discussion on Structures below.

The default pointer size is set based on the processor and compiler selected when the Program is imported and generally matches the size of the ram or equivalent address space. Different pointer sizes within the same Program are possible. The Decompiler generally expects the pointer size to match the size of the address space being pointed to, but individual architectures can model different size pointers into the space (such as near pointers).

For processors with more than one memory address space, pointer data-types do not by default indicate a preferred address space and can be used to reference data in any address space. Where there is ambiguity, the Decompiler attempts to determine the correct address space from the context of its use within the function. It is possible to create pointer data-types with an explicitly preferred address space, see .

###### Array

Array data-types are fully supported. The array element can be any other supported data-type with a fixed size.

For code that accesses arrays, the Decompiler keeps track of the array index and automatically hides the underlying multiplication needed to account for the size of an element. The access is displayed as an expression using standard square brace notation, '[' and ']'. For an access that covers more than one array element simultaneously, the Decompiler will either generate a pointer expression that casts to a data-type of the correct size or may generate a special token representing the accessed portion of the array.

    	      text[iVar1] = 'a';           // Assigning a character to a variable index of the array
    	      cVar2 = text[7];             // Reading a fixed element from an array
    	      text._8_2_ = 0x7677;         // Auto-generated token indicating multiple elements are assigned at once

For an auto-generated token like `_8_2_`, the first integer indicates the offset in bytes of the access from the start of the array, and the second integer indicates the number of bytes being accessed.

If more then one element is being accessed simultaneously, the Decompiler may try to split the access into logical pieces. See the description of the analysis option for Splitting Array Accesses.

###### Structure

Structure data-types are fully supported. The Decompiler does not automatically infer structures when analyzing a function; it propagates them into the function from explicitly annotated sources, like input parameters or global variables. Decompiler-directed creation of structures can be triggered by the user (see ).

For variables that are known to be structures, or pointers to structures, the Decompiler keeps track of offsets into the variable and will render the name of the specific field being accessed, using language specific access operators such as '.' or '->'. If the part of the structure being accessed does not have a normal field name, either because the structure data-type does not list a name at that position or because more than one field is being accessed simultaneously, the Decompiler will either cast a pointer to a data-type of the correct size or may automatically generate a token name representing the accessed portion.

    	      struct1.a = 1;                // Assigning an integer to a field named "a"
    	      fVar1 = ptr->b;               // Reading field "b" through a pointer
    	      struct1._20_4_ = 0xff00ff00;  // Auto-generated name for assigning multiple fields at once

For an auto-generated token like `_20_4_`, the first integer indicates the offset in bytes of the access from the start of the structure, and the second integer indicates the number of bytes being accessed.

If more than one field is being accessed simultaneously, the Decompiler may try to split the access into logical pieces. See the description of the analysis option for Splitting Structure Accesses.

###### Bitfields

Bitfields are fully supported. Bitfields are a special type of integer field, defined within a structure data-type, that does not respect byte boundaries. A bitfield can be as small as a single bit, and multiple bitfields can be packed into a single byte or word of the structure. The Decompiler does not infer bitfields, but propagates them into the function from structures that explicitly define them.

The Decompiler will attempt to display reads and writes to individual bitfields using the field's name and a standard structure access operator, like '.' or '->'. This hides the longer sequence of byte-based operations that the underlying code is using to isolate the individual bitfield from its neighbors.

    	      iVar1 = ptr->bit1;        //  iVar1 = ((*ptr) >> 3) & 7
    	      struct1.bit1 = i;         //  struct1._0_1 = ((i & 7) << 3) | (struct1._0_1 & 0xc7)

If a code sequence sets multiple bitfields simultaneously, the Decompiler will display the sequence using multiple assignment statements, one for each bitfield affected. If bitfields are read simultaneously, the Decompiler will display each bitfield as a separate element of the expression. If a code sequence does not seem to respect the boundaries of individual bitfields, the Decompiler will revert to using auto-generated, byte-based, field tokens to represent the sequence.

###### Enumeration

Enumerations are fully supported. The Decompiler can propagate enumerations from explicitly annotated sources throughout a function onto constants, which are then displayed with the appropriate label from the definition of the enumeration. If the constant does not match a single value in the enumeration definition, the Decompiler attempts to build a matching value by or-ing together multiple labels. The Decompiler can be made to break out constants representing packed flags, for instance, by labeling individual bit values within an enumeration.

###### Function Definition

A Function Definition in Ghidra is a data-type that encodes information about the parameters and return value for a generic/unspecified function. A formal function pointer is supported by the Decompiler as a pointer data-type that points to a Function Definition. A Function Definition specifically encodes:

- The name and data-type of each parameter.
- Whether the function takes a variable number of parameters.
- The data-type associated with the return value.
- The name of a generic calling convention associated with the function.

The Function Definition itself does not encode any storage information. Once the Function Definition is associated with a Program, its generic calling convention maps to one of the specific prototype models for the processor and compiler. The prototype model is then used to assign storage for parameters and return values, wherever the Function Definition is applied. A Function Definition is currently limited to a prototype model with one of the following names:

- __stdcall
- __thiscall
- __fastcall
- __cdecl
- __vectorcall

###### Unions

Unions data-types are fully supported. The Decompiler does not automatically infer unions when analyzing a function; it propagates them into the function from explicitly annotated sources, like input parameters or global variables.

A union data-type, similarly to a structure, is made up of component data-types called fields. But unlike a structure, a union's fields all share the same underlying storage. When the union is applied to a variable, each field potentially describes the whole variable. At any given point where the variable is read or written, a different field may be in effect, even if the underlying data hasn't changed. The decompiler attempts to infer the particular field by following data-flow to or from the point of use to determine which field best aligns with the specific operations being applied to the variable. The name of this recovered field is then printed in Decompiler output using syntax similar to that used for structure fields.

Depending on the number and variety of fields within the union, it may not be possible to fully distinguish which field is being used in a specific context. In this situation, the Decompiler chooses the first field from the list of best matches. The user has the option of changing this choice with the action.

###### Typedefs

Typedef data-types are fully supported. The Decompiler does not automatically infer typedefs when analyzing a function; it propagates them into the function from explicitly annotated sources.

A typedef is copy of another data-type but with an alternate name. In most cases it can be used interchangeably with the data-type it copies. In general, the Decompiler treats a typedef as a distinct data-type, and it will maintain its identify when it is assigned to variables and is propagated through data-flow.

Ghidra supports a specific set of attributes that can be placed directly on a typedef that then distinguish it from the data-type it copies. This allows Ghidra to support some non-standard data-types, although the typedef and its copy are no longer interchangeable. The decompiler supports the following typedef properties:

- Component Offset - See
- Address Space - See

##### Pointer Attributes

The Decompiler supports some specialized attributes that can be applied to pointer data-types, like offsets and address spaces (See below). Ghidra implements these attributes on top of typedef data-types only. In order to add attributes to pointers, a typedef of the underlying pointer data-type must be created first. Attributes can then be placed directly on the typedef from the Data Type Manager window (See Pointer-Typedef Settings).

###### Offset Pointers

An offset pointer points at a fixed offset relative to the start of its underlying data-type. Typically the underlying data-type is a structure and the pointer points at a specific field in the interior of the structure. But in general, the underlying data-type can be anything, and the offset can point anywhere relative to that data-type, including either before or after.

An offset pointer is defined with all the same properties of a normal pointer. It has an underlying data-type and a size. On top of this an offset is specified as an integer attribute on the pointer (typedef). This is the number of bytes that need to be added to the start of the underlying data-type to obtain the address actually being pointed at.

Because the underlying data-type does not start directly at the address contained in the offset pointer, one can also refer to the offset pointer's direct data-type, i.e. the data-type that is directly at the address contained in the pointer. If the pointer's offset is positive (and small), the direct data-type will generally be that of a field of the underlying data-type. If the offset is bigger than the size of the underlying data-type or is negative, the direct data-type will be undefined.

Offset pointers occur in code where the compiler has maintained knowledge of the position of an underlying data-type relative to a pointer, even if the pointer no longer points directly at the data-type. Because of this, the code may still access fields of the underlying data-type through the pointer. Annotating a variable with an offset pointer allows the Decompiler to recover these accesses.

Within the Decompiler's output, the token `ADJ` is used to indicate that the code is accessing the underlying data-type through the offset pointer. The token uses functional syntax to indicate the particular offset pointer. Then, once the `ADJ` token is applied, additional pointer syntax is used, i.e. `->`, to indicate what part of the underlying data-type is being accessed.

                  ADJ(structoffptr)->field1 = 2;  // Accessing the underlying structure's field
                  iVar1 = *ADJ(intoffptr);        // Accessing the underlying integer data-type
                  ADJ(arrayoffptr)[4] = iVar2;    // Accessing the underlying array

If the offset pointer appears in Decompiler output without the `ADJ` token being applied, it is being treated as if it were a normal pointer to its direct data-type. This generally indicates the pointer is being used to access data outside the underlying data-type.

###### Address Space Pointers

An address space pointer is a normal pointer data-type with a specific address space associated to it (See ). Its created by setting the Address Space attribute on a typedef of a pointer. The attribute value is the name of the specific address space.

Address space pointers are useful, when a program architecture supports more than one address space containing addressable memory, such as separate `code` and `data` address spaces. For a program and a specific section of its code that manipulates a pointer, it may not be easy to determine which address space is being referred to. Address space pointers provide an additional annotation mechanism to help the decompiler identify the correct address space for a pointer in context.

The Decompiler will automatically propagate an address space pointer data-type from parameters and other annotated variables associated with a function. Any constant that the pointer reaches via propagation is assumed to point into the address space associated with the pointer. The correct symbol can then be looked up, further informing the Decompiler output.

##### Forcing Data-types

The Decompiler performs type propagation as part of its analysis on functions. Data-type information is collected from variable annotations and other sources, which is then propagated via data flow throughout the function to other variables and constants where the data-type may not be immediately apparent.

With few exceptions, a variable annotation is forcing on the Decompiler in the sense that the storage location being annotated is considered an unalterable data-type source. During type propagation, the data-type may propagate to other variables, but the variable representing the storage location being annotated is guaranteed to have the given name and that data-type; it will not be overridden.

Users should be aware that variable annotations are forcing on the Decompiler and may directly override aspects of its analysis. Because of this, variable annotations are the most powerful way for the user to affect Decompiler output, but setting an incomplete or incorrect data-type as part of an annotation may produce poorer Decompiler output.

The major exception to forcing annotations is if the data-type in the annotation is undefined. Ghidra reserves specific names to represent formally undefined data-types, such as:

- undefined1
- undefined2
- undefined4
- undefined8

These allow annotations to be made even when the user doesn't have information about a variable's data-type. The number in the name only specifies the number of bytes in the variable.

The Decompiler views a variable annotation with an undefined data-type only as an indication of what name should be used if a variable at that storage address exists. The data-type for the variable is filled in, using type propagation from other sources.

For annotations that specifically label a function's formal parameters or return value, the Signature Source also affects how they're treated by the Decompiler. If the Signature Source is set to anything other than DEFAULT, there is a forced one-to-one correspondence between variable annotations and actual parameters in the Decompiler's view of the function. This is stronger than just forcing the data-type; the existence or nonexistence of the variable itself is forced by the annotation in this case. If the Signature Source is forcing and there are no parameter annotations, a void prototype is forced on the function.

A forcing Signature Source is set typically if debug symbols for the function are read in during Program import (IMPORTED) or if the user manually edits the function prototype directly (USER_DEFINED).

If an annotation and the Signature Source force a parameter to exist, specifying an undefined data-type in the annotation still directs the Decompiler to fill in the variable's data-type using type propagation. The same holds true for the return value; an undefined annotation fixes the size of the return value, but the Decompiler fills in its own data-type.

The Decompiler may still use an undefined data-type to label a variable, even after type propagation. If a variable is simply copied around within a function and there are no other substantive operations or annotations on the variable, the Decompiler may decide the undefined data-type is appropriate.

#### Variable Storage

Every variable annotation is associated with a single storage location, where the value of the variable is stored during execution: generally a register, stack location, or an address in the load image of the Program. The storage location does not necessarily hold the value for that variable at all points of execution, and it is possible for the variable value to be held in different storage locations at different points of execution. The set of execution points where the storage location does hold the variable value is called the annotation scope; this is distinct from, but influenced by, the scope of the variable itself. The different types of storage location are listed below.

##### Load-image Address

A load-image address is a concrete address in the load image of the Program, typically in the ram address space. This kind of storage must be backed by a formal memory block for the Program, which typically corresponds to a specific program section, such as the `.text` or `.bss` section. Because it is in the load image directly, an annotation with this storage shows up directly in any Listing window and can be directly manipulated there. In much of the Ghidra documentation, these annotations are referred to as Data. See the Data section, in particular.

Although specific architectures may vary, a storage location at a load image address generally represents a formal global variable, and the annotation is in scope across all Program execution. For the Decompiler, the storage location is treated as a a single persistent variable in all functions that reference it. Within a function, all distinct references (varnodes) to the storage location are merged. The Decompiler expects a value at the storage location to exist from before the start of the function, and any change to the value must be explicitly represented as an assignment to the variable in Decompiler output.

##### Stack Address

A stack address is an address in the stack frame of a particular function in the Program. Formally, a stack address is defined as an offset relative to the incoming value of the stack pointer and exists in the stack address space associated with the function. See the discussion in . A stack annotation then is a variable annotation with a stack address as its storage location. It exists only in the scope of a single function and the variable must be local to that function.

Within a Listing window, a stack annotation is displayed as part of the function header at the entry point address of the function, with a syntax similar to:

`undefined4 Stack[-0x14]:4 local_14`
The middle field (the Variable Location field) indicates that the storage location is on the stack, and the value in brackets indicates the offset of the storage location relative to the incoming stack pointer. The value after the colon indicates the number of bytes in the storage location.

Currently, the entire body of the function is included in the scope of any stack annotation, and the Decompiler will allow only a single variable to exist at the stack address. A stack annotation can be a formal parameter to the function, but otherwise the Decompiler does not expect to see a value that exists before the start of the function.

The Decompiler will continue to perform copy propagation and other transforms on stack locations associated with a variable annotation. In particular, within Decompiler output, if the value is simply copied to another location, a specific write operation to a stack address may not show up as an explicit assignment to its variable.

##### Register

A variable annotation can refer to a specific register for the processor associated with the Program. In general, such an annotation will be for a variable local to a particular function. Within a Listing window, this annotation is displayed as part of the function header, with syntax like:

`int EAX:4 iVar1`
The Variable Location field displays the name of the particular register attached to the annotation, and the value after the colon indicates the number of bytes in the register.

For local variable annotations with a register storage location, there is an expectation that the register may be reused for different variables at different points of execution within the function. There may be more than one annotation, for different variables, that share the same register storage location. An annotation is associated with a first use point that describes where the register first holds a value for the particular variable (see the discussion - ). The entire scope of the annotation is limited to the address regions between the first use point and any points where the value is read. The Decompiler may extend the scope as part of its merging process, but the full extent is not stored in the annotation.

##### Temporary Register

Variable annotations can have a temporary register as a storage location. A temporary register is not specific to a processor but is produced at various stages of the decompilation process. See the discussion of the unique space in . These registers do not have a meaningful name, and the specific storage address may change on successive decompilations. So, within a Listing window, this annotation is displayed as part of the function header with syntax like:

`int HASH:5f96367122:4 iVar2`
The Variable Location field displays the internal hash used to uniquely identify the temporary register within the data flow of the function.

A temporary register annotation must be for a local variable, and as with an ordinary register, the annotation is associated with a first use point that describes where the temporary register first holds a value for the variable.

### Function Prototypes

Every formal Function in Ghidra is associated with a set of variable annotations and other properties that make up the function prototype. Due to the nature of reverse engineering, the function prototype may include only partial information and may be built up over time. Individual elements include:

Input Parameters

  Each formal input to the function can have a Variable Annotation that describes its name, data-type, and storage location. The storage location applies at the moment control flow enters the function. If annotations exist, they are shown in a Listing window as part of the Function header, and they usually correspond directly with symbols in the function declaration produced by the Decompiler.

Return Value

  The value returned by a function can have a special Variable Annotation that describes its data-type and storage location. The storage location applies at the moment control flow exits the function. If it exists, the annotation is shown in a Listing window as part of the Function header with the name `<RETURN>`, and it usually corresponds directly with the return value in the function declaration produced by the Decompiler.

Auto-Parameters

  Specific prototypes may require auto-parameters like this or __return_storage_ptr__. These are special input parameters that compilers may use to implement specific high-level language concepts. See the discussion in . Within Ghidra, auto-parameters are automatically created by the Function Editor Dialog if the desired prototype requires them. Within a Listing window, auto-parameters look like other parameter annotations, but the storage field shows the string `(auto)`. Decompiler output will generally display auto-parameters as explicit variables rather than hiding them.

Calling Convention

  The calling convention used by the function is specified as part of the function prototype. The convention is specified by name, referring to the formal that describes how storage locations are selected for individual parameters along with other information about how the compiler treats the function. Available models are determined by the processor and compiler, but may be extended by the user (see ).

  In the absence of input parameter and return value annotations, the Decompiler will use the prototype model as part of its analysis to discover the input parameters and the return value of the function.

  The name unknown is reserved to indicate that nothing is known about the calling convention. If set to unknown, depending on context, the Decompiler may assign the calling convention based on the Prototype Evaluation option (see ), or it may use the default calling convention for the architecture.

Variable Arguments

  Functions have a boolean property called variable arguments, which can be turned on if the function is capable of being passed a variable number of inputs. This property informs the Decompiler that the function may take additional parameters beyond any with an explicit variable annotation. This affects decompilation of any function which calls the variable arguments function, allowing the Decompiler to discover unlisted parameters at a given call site.

No Return

  A function can be marked with the no return property, meaning that once a call is made to the function, execution will never return to the caller. The Decompiler uses this to compute the correct control flow in any calling functions.

In-Line

  If the in-line property is turned on for a particular function, it directs the Decompiler to inline the effects of the function into the decompilation of any of its calling functions. The function will no longer appear as a direct function call in the decompilation, but all of its data flow will be incorporated into the calling function.

  This is useful for bookkeeping functions, where it is important for the Decompiler to see its effects on the calling function. Functions that set up the stack frame for a caller or functions that look up or dispatch a switch destination are typical examples that should be marked in-line.

Call-fixup

  This property is similar in spirit to marking a function as in-line. A call-fixup directs the Decompiler to replace any call to the function with a specific chunk of raw p-code. The decompilation of any calling function no longer shows the function call, but the chunk of p-code incorporates the called function's effects.

  Call-fixups are more flexible than just inlining a function. The call-fixup chunk can be tailored to incorporate all of, just a part of, or something different to the behavior of the function.

  Call-fixups are specified by name. The name and associated p-code chunk are typically defined in the compiler specification for the Program. Users can extend the available set of call-fixups (see ).

#### Signature Source

Ghidra records a Signature Source for every function, indicating the origin of its prototype information. This is similar to the Symbol Source attached to Ghidra's symbol annotations (see the documentation for Filtering in the Symbol Table). The possible types are:

- DEFAULT - for basic or no information
- AI - for information that is produced with AI assistance
- ANALYSIS - for information derived by an Analyzer
- IMPORTED - for information imported from an external source
- USER_DEFINED - for information set by the user

Upon import of the Program, if there are debugging symbols available, Ghidra will build annotations of the function's parameters and set the Symbol Source type to IMPORTED. Otherwise, it will generally be set to DEFAULT.

However, Ghidra adjusts the Signature Source for a function if there is any change to the prototype. In particular, if the user adds, removes, or edits variable annotations for the function's parameters or return value, Ghidra automatically converts the Signature Source to be USER_DEFINED.

If the Signature Source is set to anything other than DEFAULT, the function's prototype information is forcing on the Decompiler (see the discussion in ).

#### Discovering Parameters

The input parameter and return value annotations of the function prototype, like any variable annotations, can be forcing on the Decompiler (see the complete discussion in ). But keep in mind:

The input parameters and return value are all forced on the Decompiler as a unit based on the Signature Source. They are all forced if the type is set to anything other than DEFAULT; otherwise none of them are forced.

If the function prototype's annotations are not forcing, the Decompiler will attempt to discover the parameters and return value using the calling convention. The prototype model underlying the calling convention dictates which storage locations can be considered as parameters and their formal ordering.

#### Custom Storage

If there are parameter or return value annotations that do not agree with the calling convention that has been set, the function prototype is said to be using custom storage. Using the Function Editor Dialog for instance, any storage location can be specified as a parameter, and a completely custom prototype can be built for the function.

The Decompiler will disregard the calling convention's rules in this situation and use the custom storage locations for parameters and the return value. Other aspects of the calling convention, like the unaffected list, will still be used.

### Data Mutability

Mutability is a description of how values in a specific memory region, either a single variable or a larger block, can change during Program execution based either on properties or established rules. Ghidra recognizes the mutability settings:

- Normal
- Constant - (read-only)
- Volatile

Mutability affects Decompiler analysis and can have a large impact on the output.

Most memory has normal mutability; the value at the memory location may change over the course of executing the Program, but for a given section of code, the value will not change unless an instruction explicitly writes to it.

Mutability can be set on an entire block of memory in the Program, typically from the Memory Map. It can also be set as part of a single Variable Annotation. From a Listing window, for instance, use the Settings dialog.

#### Read-only

The constant mutability setting indicates that values within the memory region are read-only and don't change during Program execution. If a read-only variable is accessed in a function being analyzed by the Decompiler, its constant value, if present in the Program's load image, replaces the variable within data flow for the function. The Decompiler may propagate the constant and fold it in to other operations, which can have a substantial impact on the final output.

#### Volatile

The volatile mutability setting indicates that values within the memory region may change unexpectedly, even if the code currently executing does not directly write to it. Accessing a variable within a volatile region, either reading or writing, can have other side-effects on the machine state, and it cannot in general be treated as normal variable. If a volatile variable is accessed in a function being analyzed by the Decompiler, each access is expressed as a copy statement on its own line, separated from other expressions, so that the its position within the code and any sequence of accesses is clearly indicated. Any access, either read or write, will always be displayed, even if the value is not directly used by the function. The token representing the variable will be displayed using the Special color, highlighting that the access is volatile (See ).

    	  X = SREG;              // Reading volatile SREG
    	  DAT_mem_002b = 0x20;   // Writing volatile DAT

### Constant Annotations

Ghidra provides numerous actions to control how a specific constant is formatted or displayed. An annotation can be applied directly to a constant in a Decompiler window, which always affects Decompiler output. Or, an annotation can be applied to the constant operand of a specific machine instruction displayed in a Listing window. In this case, to the extent possible, the Decompiler attempts to track the operand and apply the annotation to the matching constant in the Decompiler output. However, the constant may be transformed from its value in the original machine instruction during the Decompiler's analysis. The Decompiler will follow the constant through one of the following simple transformations, but otherwise the annotation will not be applied.

- Signed or zero extension
- Bitwise negation
- Integer negation - Two's complement
- Add or subtract 1

#### Equates

Ghidra can create an association between a name and a constant, called an equate. An equate is a descriptive string that is intended to replace the numeric form of the constant, and equates across the entire Program can be viewed from the Equates Table.

An equate can be applied to a machine instruction with a constant operand by using the Set Equate menu from a Listing window. If the Decompiler successfully follows the operand to a matching constant, the equate's name is displayed as part of the Decompiler's output as well as in any Listing window. A transformed operand is displayed as an expression, where the transforming operation is applied to the equate symbol representing the original constant.

Alternatively, an equate can be applied directly to a constant from a Decompiler window using its menu. The constant may or may not have a corresponding instruction operand but will be displayed in Decompiler output using the descriptive string.

#### Format Conversions

Ghidra can apply a format conversion to any integer constant that is displayed in Decompiler output.

A conversion can be applied to the machine instruction containing the constant as an operand using the Convert menu option from a Listing window. If the Decompiler successfully traces the operand to a matching constant, the format conversion is applied in the Decompiler output as well as in the Listing window.

Alternately, a conversion can be applied directly to an integer constant in a Decompiler window using its menu option. The constant may or may not have a corresponding instruction operand but is displayed in Decompiler output using the conversion.

Conversions applied by the Decompiler are currently limited to:

- Binary - 0b01100001
- Decimal - 97
- Hexadecimal - 0x61
- Octal - 0141
- Char - 'a'

If necessary, a header matching the format is prepended to the representation string, either "0b", "0x" or just "0". A conversion will not switch the signedness of the constant; the signed or unsigned data-type associated with the constant, as determined by analysis, is preserved. If the constant is negative, with a signed data-type, the representation string will always start with a '-' character.

### Register Values

A register value in this context is a region of code in the Program where a specific register holds a known constant value. Ghidra maintains an explicit list of these values for the Program (see the documentation for Register Values), which the Decompiler can use when analyzing a function. A register value benefits Decompiler analysis, especially if the original compiler was aware of the constant value, as the Decompiler can recover address references calculated as offsets relative to the register and otherwise propagate the constant.

A register value is set by highlighting the region of code in a Listing window and then invoking the Set Register Values... command from the pop-up menu. The beginning and end of a region is indicated in a Listing window with `assume` directives, and regions can be generally viewed from the Register Manager window.

In order for a particular register value to affect decompilation, the region of code associated with the value must contain the entry point of the function, and of course the function must read from the register. Only the initial reads of the register are replaced with the constant value. The Decompiler will continue to respect later instructions that write to the register, even if the instruction is inside the register value's region. If a register value's region starts in the middle of a function, decompilation is not affected at all.

#### Context Registers

There is a special class of registers called context registers whose values have a different affect on analysis and decompilation than described above.

Context registers are inputs to the disassembly decoding process and directly affect which machine instructions are created.

The value in a context register is examined when Ghidra decodes machine instructions from the underlying bytes in the Program. A specific value generally corresponds to a specific execution mode of the processor. The ARM processor T bit, for instance, which selects whether the processor is executing ARM or THUMB instructions, is modeled as a context register in Ghidra. The same set of bytes in the Program can be decoded to machine instructions in more than one way, depending on context register values.

Bytes are typically decoded once using context register values established at the time of disassembly. From Ghidra's more static view of execution, a context register holds only a single value at any point in the code, but the same context register can hold different values for different regions of code. Setting a new value on a region of the Program will affect any subsequent disassembly of code within that region.

If a context register value is changed for a region that has already been disassembled, in order to see the affect of the change, the machine instructions in the region need to be cleared, and disassembly needs to be triggered again (see the documentation on the Clear Plugin).

Values for a context register are set in the same way as for any other register, using the Set Register Values... command described above. Within the Register Manager window, context registers are generally grouped together under the contextreg pseudo-register heading. For details about how context registers are used in processor modeling, see the document "SLEIGH: A Language for Rapid Processor Specification."

Because context registers affect machine instructions, they also affect the underlying p-code and have a substantial impact on decompilation. Although details vary by processor, context register values are typically established during the initial import and analysis of a Program and aren't changed frequently.

## Decompiler Options

This page lists configuration options that explicitly affect the behavior of the Decompiler or its output, independent of the code that is being decompiled. The bulk of these options are accessible by selecting the Code Browser menu

Edit -> Tool Options...
and then picking the Decompiler folder. The options are associated with the particular Code Browser or other tool being used and will apply to decompilation of any Program being analyzed by that tool. There are three categories of options, which are listed by clicking either on the Decompiler folder or one of its two subsections.

- Decompiler - lists that affect the engine behavior.
- Analysis - lists that affect the Decompiler's transformation process.
- Display - lists that affect the final presentation of Decompiler output.

Options that are specific to the particular Program being analyzed are accessed by selecting the Code Browser menu

Edit -> Options for <program>....
Picking the Decompiler section shows that only affect the Decompiler. Picking the section shows a table of the available prototype models, call-fixups, and callother-fixups. These affect more than just the Decompiler but are also documented here.

### General Options

These options govern what resources are available to the Plug-in and the Decompiler engine but do not affect how analysis is performed or results are displayed.

Cache Size (Functions)

  Producing decompilation results for a single function can be computationally intensive. This option specifies the number of functions whose decompilation results can be cached simultaneously. When navigating to a function that has been recently cached, as when navigating back and forth between a few functions, a new decompilation is not triggered.

Decompiler Max-Payload (MBytes)

  This option limits the number of bytes that can be produced by the Decompiler process as output when decompiling a single function. A payload includes the actual characters to be displayed in the window, additional token markup, symbol information, and other details of the underlying syntax tree. The limit is specified in megabytes of data. If the limit is exceeded for a single function, decompilation is aborted for that function, and an error message "Decompiler results exceeded payload limit ..." is displayed.

Decompiler Timeout (seconds)

  This option sets an upper limit on the number of seconds the Decompiler spends attempting to analyze one function before aborting. It is currently not enforced for a Decompiler window. Instead it applies to the DecompilerSwitchAnalyzer, the `analyzeHeadless` command, scripts, and other plug-ins that make use of the Decompiler service.

Max Instructions per Function

  This option sets a maximum number of machine instructions that the Decompiler will attempt to analyze for a single function, as a safeguard against analyzing a long sequence of zeroes or other constant data. The Decompiler will quickly throw an exception if it traces control flow into more than the indicated number of instructions.

Max Entries per Jumptable

  This option sets the maximum number of entries (addresses) that the Decompiler can recover from analyzing a single jumptable. This serves as a sanity check that the recovered dimensions of a jumptable are reasonable and places an upper limit on the sheer number of addresses the Decompiler is willing to trace from a single indirect jump.

### Analysis Options

These options directly affect how the Decompiler performs its analysis, either by toggling specific analysis passes or changing how it treats various annotations.

Alias Blocking

  When deciding if an individual stack location has become dead, the Decompiler must consider aliases, pointers onto the stack that could be used to modify the location within a called function. One strong heuristic the Decompiler uses is: if the user has explicitly created a variable on the stack between the base location referenced by the pointer and the individual stack location, then the Decompiler can assume that the pointer is not an alias of the stack location. The alias is blocked by the explicit variable. However, if the user's explicit variable is labeling something that isn't really an explicit variable, like a field within a larger structure, for instance, the Decompiler may incorrectly consider the stack location as dead and start removing live code.

  In order to support the exploratory labeling of stack locations, the user can use this setting to specify what data-types should be considered blocking. The four options are:

  - None - No data-type is considered blocking
  - Structures - Only structures are blocking
  - Structures and Arrays - Only structures and arrays are blocking
  - All Data-types - All data-types are blocking
  Selecting None is the equivalent of turning off the heuristic. Selecting anything except All Data-types allows users to safely label small variables without knowing immediately if the stack location is part of a larger structure or array.
Eliminate unreachable code

  When toggled on, the Decompiler eliminates code that it considers unreachable. This usually happens when, due to constant propagation and other analysis, the Decompiler decides that a boolean value controlling a conditional branch can only take one possible value and removes the branch corresponding to the other value. Toggling this to off lets the user see the dead code, which is typically demarcated by the control-flow structure:

      	      if (false) { ... }

Ignore unimplemented instructions

  When toggled on, the Decompiler treats instructions whose semantics have been formally marked unimplemented as if they do nothing (no operation). Crucially, control flow falls through to the next instruction. In this case, the Decompiler inserts the warning "Control flow ignored unimplemented instructions" as a comment in the function header, but the exact point at which instruction was ignored may not be clear. If this option is toggled off, the Decompiler inserts the built-in function `halt_unimplemented()` at the point of the unimplemented instruction, and control flow does not fall through.

Infer constant pointers

  When toggled on, the Decompiler infers a data-type for constants it determines are likely pointers. In the basic heuristic, each constant is considered as an address, and if that address starts a known data or function element in the program, the constant is assumed to be a pointer. The constants are treated like any other source of data-type information, and the inferred data-types are freely propagated by the Decompiler to other parts of the function.

NaN operations

  This option determines how the Decompiler treats floating-point NaN (Not a Number) operations. Many processors automatically perform NaN checks on the operands of floating-point instructions, and unless specifically configured, these show up in Decompiler output as `NAN()` functional tokens. Common floating-point source code operations, like `<`, `>`, and `==` can generate `NAN` tokens as a side effect, even if the original source code was not designed to handle NaN values, and the tokens can clutter the output.

  The user can optionally configure some or all of the NaN operations to be ignored, meaning that inputs to the NaN operation are assumed to be valid floating-point values and the `NAN` function is removed, replacing it with the value: false. The possible settings are:

  - Ignore none - No NaN operations are removed
  - Ignore with comparisons - NaN operations associated with comparisons are removed
  - Ignore all - All NaN operations are removed
  The Decompiler considers a NaN operation to be associated with a floating-point comparison if they both can be considered boolean clauses of the same if condition.
Recover -for- loops

  When toggled on, the Decompiler attempts to pinpoint variables that control the iteration over specific loops in the function body. When these loop variables are discovered, the loop is rendered using a standard for loop header that contains an initializer statement, condition, and iterating statement.

      	      for (iVar2 = 10; iVar2 < len; iVar2 = iVar2 + 1) { ...

  When toggled off, the loop is displayed using while syntax, with any initializer and iterating statements mixed in with the loop body or preceding basic blocks.

Respect read-only flags

  When toggled on, the Decompiler treats any values in memory marked read-only as constant. If a read-only memory location is explicitly referenced by the function being decompiled, it is considered to be unchanging, and the initial value present in the Program is pulled into the data flow of the function as a constant. Due to Constant Propagation and other transformations, read-only memory can have a large effect on Decompiler output.

  Typically, as part of the import process, Ghidra marks memory blocks as read-only if they are tagged as such by a section header or other meta-data in the original binary. Users can actively set whether specific memory regions are considered read-only through the Memory Manager, and individual data elements can be marked as constant via the Mutability setting (see ).

Simplify bitfield access

  When this option is active, the Decompiler attempts to identify expressions where bitfields, as defined in structure data-types, are either being written to or read from. Any sequence of logical operations that access an individual bitfield are collapsed into a normal field access, displaying the bitfield's name.

      	      uVar1 = my1._3_1 << 2 & 3;  // Isolating a 2-bit field 'mode' within variable 'my1'
      	        ...
                    uVar1 = my1.mode;   // The same assignment after simplification

Simplify extended integer operations

  This toggles whether the Decompiler attempts to simplify double precision arithmetic operations, where a single logical operation is split into two parts, calculating the high and low pieces of the result in separate instructions. Decompiler support for this kind of transform is currently limited, and only certain constructions are simplified.

Simplify predication

  When this option is active, the Decompiler simplifies code sequences containing predicated instructions. A predicated instruction is executed conditionally based on a boolean value, the predicate, and a sequence of instructions can share the same predicate. The Decompiler merges the resulting `if/else` blocks that share the same predicate so that the condition is only printed once.

Split combined structure fields

  When this option is active, the Decompiler attempts to identify places in the code where multiple fields of a structure data-type are being moved simultaneously with a single operation. Then it splits the operation into multiple pieces so that the logical fields can be seen individually. When this option isn't active, the Decompiler creates an artificial token to represent the combined fields being written to or read from.

      	      struct1._20_4_ = 0xff00ff00;  // Auto-generated name for assigning multiple fields at once
      	        ...
      	      struct1.a = 0xff00;           // The same assignment, after splitting
      	      struct1.b = 0xff00;

Split combined array elements

  When this option is active, the Decompiler attempts to identify places in the code where multiple elements of an array are being moved simultaneously with a single operation. Then it splits the operation into multiple pieces so each element of the array can be seen individually. When this option isn't active, the Decompiler creates an artificial token to represent the combined elements being written to or read from.

      	      text._20_2_ = 0x4241;        // Auto-generated name for assigning multiple elements at once
      	        ...
      	      text[20] = 'A';              // The same assignment, after splitting
      	      test[21] = 'B';

Split pointers to combined elements

  This options affects when the Decompiler's splitting actions are applied. See the discussion above about Splitting Structure Accesses and Splitting Array Accesses. If this option is on, a split is performed whenever combined elements or combined fields are copied. In particular, either the read access, or the write access, or both, can be through a pointer. If this option is off, splitting is limited to copies between structures or arrays at fixed locations, either at a global address, or on the local stack.

Use in-place assignment operators

  When toggled on, the Decompiler employs in-place assignment operators, such as `+=` and `<<=`, in its output syntax.

### Display Options

These options do not change the Decompiler's analysis but only affect how the results are presented.

Background Color

  Assign the background color for the Decompiler window.

Brace Format for <kind-of> blocks

  Choose how braces are placed after function declarations, or other kinds of code blocks in Decompiler output. Formatting can be controlled for:

  - function blocks - the main function bodies
  - if/else blocks - blocks delineated by the `if` and `else` keywords
  - loop blocks - blocks delineated by the `for`, `do`, and `while` keywords
  - switch blocks - blocks delineated by the `switch` keyword
  The different formatting options primarily control how the opening brace is displayed relative to the line containing the declaration or keyword starting the block. The formatting options are:
  - Same line - opening brace placed on same line
  - Next line - opening brace placed on the next line
  - Skip one line - opening brace placed on line after a blank line

  The "Same line" option is consistent with K & R code formatting style. The "Next line" option is consistent with the Allman formatting style.

Color Default

  Assign the color to any characters emitted by the Decompiler that do not fall into one of token types listed below. This includes delimiter characters like commas and parentheses as well as various operator characters.

Color for <token>

  Assign colors to the different types of language tokens emitted by the Decompiler. These include:

  - Comments
  - Constants - including integer, floating-point, character, and string
  - Functions names
  - Globals - names of variables with global scope
  - Keywords - reserved names in the language being emitted
  - Parameters - names of function input variables
  - Types - names of data-types in variable declarations and casts
  - Variables - names of local variables
  - Special - volatile variables and other special symbols
Color for Current Variable Highlight

  Assign the background color used to highlight the token currently under the cursor in a Decompiler window.

Color for Highlighting Find Matches

  Assign the background color used to highlight characters matching the current Find pattern (see ).

Color for Highlighting Middle-mouse Matches

  Assign the background color used to highlight characters when highlighting using the middle-mouse button.

Comment line indent level

  Set the number of characters that comment lines are indented within Decompiler output. This applies only to comments within the body of the function being displayed. Comments at the head of the function are not indented.

Comment style

  Set the language syntax used to delimit comments emitted as part of Decompiler output. For C and Java, the choices are `/* C style comments */` and `// C++ style comments`.

Disable printing of type casts

  Set whether the syntax for type casts is emitted in Decompiler output. If this is toggled on, type cast syntax is never displayed, even when rules of the language require it. So individual statements may no longer be formally accurate.

Display <kind-of> Comments

  Set whether a specific type of comment should be incorporated into Decompiler output. Each type has its own toggle and can be individually included or excluded from Decompiler output.

  - EOL
  - PLATE - Whether plate comments within the body of the function are displayed
  - POST
  - PRE
  A comment's type indicates how it is placed within a Listing window, not how it is placed in a Decompiler window. All comments within the body of the function are displayed in the same way by the decompiler, regardless of their type (see the discussion in ).
Display Header comment

  Toggle whether the Decompiler emits comments at the head (before the beginning) of a function. The header is built from Plate comments placed at the entry point of the function (see the discussion in ). The inclusion of other Plate comments is controlled by the Display PLATE comments toggle, described above.

Display Line Numbers

  Toggle whether line numbers are displayed in any Decompiler window. If toggled on, each Decompiler window reserves space to display a numbers down the left side of the window, labeling each line of output produced by the Decompiler. Line numbers are associated with the window itself and are not formally part of the Decompiler's output.

Display Namespaces

  Control how the Decompiler displays namespace information associated with function and variable symbols. The possible settings are:

  - Minimally - Display the minimal path that distinguishes the symbol
  - Always - Always display the entire namespace path
  - Never - Never display the namespace path

  The Minimally setting, which is the default, will only emit the portion of the namespace path necessary to distinguish the symbol from other symbols with the same base name used by the function, or if a portion of the path is completely outside the function's scope.

  The Never setting never displays any of the namespace path under any circumstances and may produce output that is ambiguous and doesn't formally parse.

Display Warning comments

  Toggle whether Decompiler generated WARNING comments are displayed as part of the output. The Decompiler generates these comments, independent of those laid down by users, to indicate unusual conditions or possible errors (see ).

Font

  Set the typeface used to render characters in any Decompiler window. Indentation is generally clearer using a monospaced (fixed-width) font, but any font available to Ghidra can be used. The size of the font can also be controlled from this option.

Integer format

  Set how integer constants are formatted in the Decompiler output. The possible settings are:

  - Force Hexadecimal - Always use a hexadecimal representation
  - Force Decimal - Always use a decimal representation
  - Best Fit - Select the most natural representation
  For Best Fit, a representation is selected based on how close it is to either a round decimal value (10, 100, 1000, etc.) or a round hexadecimal value (0x10, 0x100, 0x1000, etc.)
Maximum characters in a code line

  Set the maximum number of characters in a line of code emitted by the Decompiler before a line break is forced. The Decompiler will not split an individual token across lines. So line breaks frequently will come before the maximum number of characters is reached, and technically a single token can extend the line beyond the maximum.

Number of characters per indent level

  Set the amount of indenting used to print statements within a nested scope in the Decompiler output. Each level of nesting (function bodies, loop bodies, if/else bodies, etc.) adds this number characters.

Print 'NULL' for null pointers

  Set how null pointers are displayed in Decompiler output. If this is toggled on, the Decompiler will print a constant pointer value of zero (a null pointer) using the special token `NULL`. Otherwise the pointer value is represented with the '0' character, which is then cast to a pointer.

Print calling convention name

  Set whether the calling convention is printed as part of the function declaration in Decompiler output. If this option is turned on, the name of the calling convention is printed just prior to the return value data-type within the function declaration. All functions in Ghidra have an associated calling convention (or prototype model) that is used during Decompiler analysis (see the discussion in ).

### Program Options

Changes to these options affect only the Decompiler and only for the current Program being analyzed.

Prototype Evaluation

  Sets the calling convention (prototype model) used when decompiling a function where the convention is not known; i.e., marked as unknown. Many architectures have multiple calling conventions, __stdcall, __thiscall, etc. (see the discussion in ).

### Specification Extensions

This entry displays elements from the Program's compiler specification and processor specification and allows the user to add or remove extensions, including prototype models, call-fixups, and callother-fixups.

Every program has a core set of specification elements, loaded from the , that cannot be modified or removed. Extensions, however, can be added to this core specification. Any extension imported from this dialog is directly associated with the active Program and is stored permanently with it.

Users can change or reimport an extension if new information points to a better definition. Users have full control over an extension, and unlike a core element, can tailor it specifically to the Program.

This options entry presents a table of all specification elements. Each element, whether core or an extension, is displayed on a separate row with three columns:

- Extension Type - indicating the type of element
- Name - showing the formal name of the element
- Status - indicating whether the element is core or an extension

The core elements of the specification have a blank Status column, and any extension is labeled either as extension or override.

#### Extension Types

Each of the element types described here represents an XML tag of the same name, which, if present in the table, must either be in the compiler specification file, the processor specification file, or provided to Ghidra as an import document.

prototype

  This element is a named that holds a specific set of parameter-passing details. It can be applied to individual functions by name, typically via the Calling Convention menu in the Function Editor Dialog. See the documentation on for how they affect decompilation.

  The XML `<prototype>` tag always has a name attribute that defines the formal name of the prototype model, which must be unique across all models.

      <prototype name="__stdcall" extrapop="unknown" stackshift="4">
        <input>
          <pentry minsize="1" maxsize="500" align="4">
            <addr offset="4" space="stack"/>
          </pentry>
        </input>
        <output>
        ...

callfixup

  This element is a Call-fixup, which can be used to substitute a specific p-code sequence for CALL instructions during decompilation, as described in .

  The `<callfixup>` tag has a name attribute listing the formal name, which must be unique across all call-fixups.

      <callfixup name="EH_prolog3">
        <pcode>
          <body><![CDATA<
            EBP = ESP + 4;
            tmp = * EBP;
            ESP = ESP - tmp;
            ESP = ESP - 24;
          ]]></body>
        </pcode>
      </callfixup>

callotherfixup

  This element is a Callother-fixup, which can be used to substitute a specific p-code sequence for CALLOTHER p-code operations. A CALLOTHER is a black-box, or unspecified p-code operation (see ).

  The `<callotherfixup>` tag has a targetop attribute which lists the name of the particular CALLOTHER operation it substitutes for.

      <callotherfixup targetop="dynamicPush">
        <pcode>
          <input name="amount"/>
          <body><![CDATA[
            RSP = RSP + amount;
          ]]></body>
        </pcode>
      </callotherfixup>

#### Status

The Status column labels an element as either a core specification or an extension; it also gives an indication of whether the element is about to be installed or removed.

With no changes pending, the column will show one of the three main values:

<blank>

  A blank Status column indicates that the element is a core part of the specification, originating from one of the specification files. These elements cannot be changed or removed.

extension

  Indicates that the element is a program-specific extension that has been added to the specification.

override

  Indicates that the element, which must be a callotherfixup, is an extension that overrides a core element with the same target. The extension effectively replaces the p-code injection of the core element with a user-supplied one. If this type of extension is later removed, the core element becomes active again.

If the user has either imported additional extensions or selected an extension for removal but has not yet clicked the Apply button in the Options dialog, the Status column may show one of the following values, indicating a pending change:

install

  Indicates a new extension that will be installed.

remove

  Indicates an extension that is about to be removed.

replace

  Indicates a new extension that will replace a current extension with the same name.

override pending

  Indicates a new extension that will override a core element when it is installed.

#### Importing a New Extension

The Import button at the bottom of the Specification Extensions pane allows the user to import one of the three element types, prototype, callfixup, or callotherfixup, into the program as a new extension. The user must supply a properly formed XML document, as a file, that fully describes the new extension. Clicking the Import button brings up a File Chooser dialog, from which the user must select their prepared XML file. Once Ok is clicked, the file is read in and validated. If there are any problems with the validation, or if the new extension's name collides with a core element, the import does not succeed and an error message will be displayed. Otherwise, the import is accepted, and the table is updated to indicate the pending change.

The final change to the program, installing the new extension, will not happen until the Apply button, at the bottom of the Options dialog, is clicked.

The XML file describing the extension must have one of the tags, `<prototype>`, `<callfixup>`, or `<callotherfixup>`, as its single root element. Users can find numerous examples within the compiler and processor specification files that come as part of Ghidra's installation (see ).

In the case of prototype and callfixup elements, extensions cannot replace existing core elements, so the new extension must not have a name that matches an existing core element. If a new callotherfixup extension has a targetop that matches a core element, the extension is automatically treated as an override.

Existing extensions can be replaced simply by importing a new extension with the same name or targetop.

#### Removing an Extension

The Remove button at the bottom of the Specification Extensions pane allows the user to remove a previously installed extension. A row from the table is selected first, which must have a Status of extension or override. Core elements of the specification cannot be removed. Clicking the Remove button brings up a confirmation dialog, and if Ok is clicked, the selected extension is marked for removal. The Status of the row changes to remove, reflecting this.

The final change to the program, removing the extension, will not happen until the Apply button, at the bottom of the Options dialog, is clicked.

If a prototype or callfixup is removed, all functions are checked to see if they have the matching calling convention or call-fixup set. A function with matching calling convention is changed to have the default convention, which is always a core element. A function with matching call-fixup is changed to have no call-fixup.

## Decompiler Window

To display the Decompiler window, position the cursor on a function in the Code Browser, then select the icon from the tool bar, or the Decompile option from the Window menu in the tool.

A Decompiler window always displays one function at a time. The initial window that comes up in the Code Browser is called the Main window (see ), and it automatically decompiles and displays the function at the current address, following the user's navigation. Other Snapshot windows can also be opened that show different functions at the same time (see ). But any window only shows one function at a time.

Decompilation for a window is performed "on-the-fly". It automatically incorporates the most recent labels, data-types, comments, and other annotations applied by the user. Any change to the Program annotations (renaming, setting data-types, etc.) automatically causes each window to redecompile its function.

The time it takes to decompile a single function is generally proportional to the number of instructions that make up the body of the function. Large functions may require a significant amount of time to decompile, and because decompilation is performed on-the-fly, closing a window or navigating away from a function runs the risk of losing results that took a long time to compute.

### Display

The window shows the decompiled output for the function associated with the window in C or some other high-level programming language. The output is tokenized following conventions of the language. Possible token types include:

- Data-type Name
- Variable Name
- Variable Sub-field Name
- Function Name
- Operator
- Label
- Comment
- Syntax

The type of token provides context for the pop-up menus, which can trigger highlighting, navigation, renaming, and other actions within the window.

If the window starts to decompile but ultimately fails to complete the decompilation, due to an error or cancellation, it displays a brief description of what caused the failure instead of the normal output. Decompilation may also successfully produce output but issue one or more warnings during the process. These warnings are integrated into the output as source code comments starting with label `WARNING:`. They occur either at the beginning of the function as part of the function header or at the point in the code directly associated with the warning (see ).

### Main Window

Initially pressing or selecting Decompile from the Window menu in the tool brings up the main window. The main window always displays the function at the current address within the Code Browser and follows as the user navigates within the Program. Any mouse click, menu option, or other action causing the cursor to move to a new address in the Listing also causes the main window to display the function containing that address. Navigation to new functions is also possible from within the window by double-clicking on function tokens (see ).

#### Cross-Highlighting

The main window maintains a map between the individual variable and operator tokens displayed in the window and the machine instructions which correspond to them. Disassembled machine instructions are displayed by any Listing window, and having both a Listing and Decompiler window side by side lets the user see this correspondence between the decompiled and disassembled views of the function. Clicking on tokens in the Decompiler window causes the Listing window to navigate to the corresponding instruction, and clicking instructions in the Listing window causes the Decompiler window to navigate to the corresponding line. Highlighting a region of code in either window causes the corresponding region in the other window to be highlighted.

Variable Name and Variable Sub-field Name tokens map to the machine instruction which wrote to the variable at that point in function.

Operator tokens map to the machine instruction which performed that operation.

Function Name tokens, if they represent a call to another function, map to the machine instruction executing the call.

Comment tokens map to the machine address associated with the comment.

In general, the map between machine instructions and tokens is not one-to-one because the Decompiler transforms its underlying representation of the function. An instruction may no longer have any operator that corresponds to it in the decompiled result. Tokens may be transformed from the natural operation of the machine instruction they are associated with or may represent the effect of multiple instructions.

### Snapshot Windows

Pressing the icon in any Decompiler window's toolbar causes a Snapshot window to be created, which shows decompilation of the same function. Unlike the main window however, the Snapshot window does not change the function it displays in response to external navigation events. A Snapshot window can be used to hold a function fixed while the user navigates to different functions in Listing or other windows.

Multiple Snapshot windows can be brought up to show decompilation of different functions simultaneously. Snapshot windows are visually distinguished from the main Decompiler window by their colored outline.

Navigating to new functions within a Snapshot window is possible when the window is active. The window responds to the actions

- Go To... (pressing the 'G' key)
- Go to previous location (Back)
- Go to next location (Forward)

Double-clicking on specific tokens within the Snapshot window may also cause it to navigate to a new location (see ).

### Undefined Functions

If the current location within the Code Browser is in disassembled code, but that code is not contained in a Formal Function Body, then the Decompiler invents a function body, on the fly, called an Undefined Function. The background color of the window is changed to gray to indicate this special state.

The entry point address of the Undefined Function is chosen by backtracking through the code's control flow from the current location to the start of a basic block that has no flow coming in except possibly from call instructions. During decompilation, a function body is computed from the selected entry point (as with any function) based on control flow up to instructions with terminator semantics.

The current address, as indicated by the cursor in the Listing for instance, is generally not the entry point of the invented function, but the current address will be contained somewhere in the body.

For display purposes in the window, the invented function is given a name based on the computed entry point address with the prefix `UndefinedFunction`. The function is assigned the default calling convention, and parameters are discovered as part of the Decompiler's analysis.

### Tool Bar

The following actions are available by pressing the corresponding icon in the title/tool bar at the top of each individual Decompiler window. The action applies to the function and Decompiler results displayed in that particular window.

#### Export to C

- button

Exports the decompiled result of the current function to a file. A file chooser dialog is displayed to select the name of the output file. If a file extension is not specified, a ".c" is appended to the filename. If the file already exists, a final dialog is presented to confirm that the file should be overwritten.

This action exports a single function at a time. The user can export all functions simultaneously from the Code Browser, by selecting the menu File -> Export Program... and then choosing C/C++ from the drop-down menu. See the full documentation for the Export dialog.

#### Snapshot

- button

Creates a new Snapshot window. The Snapshot window displays the same function as the Decompiler window on which the action was triggered, and if that window navigates to other functions, the Snapshot does not follow but continues to display the original function (see ).

#### Re-decompile

- button

Triggers a re-decompilation of the current function displayed in the window. Any cached results are discarded, and a full decompile is performed.

This action is not necessary for normal reverse engineering tasks. Re-decompilation is automatically triggered for all Decompiler windows by any change to the Program, so the most up-to-date decompilation is always available to the user without this action. This action is primarily a debugging aid for plug-in developers.

#### Eliminate Unreachable Code

- toggle button

Quickly turn off the decompiler setting.

#### Respect Read-only Flags

- toggle button

Quickly turn off the decompiler setting.

#### Copy

- button

Copies the currently selected text in the Decompiler window to the clipboard.

#### Debug Function Decompilation

This action is located in the drop-down menu on the right side of the Decompiler window tool/title bar.

Information suitable for debugging the decompilation process for the current function is collected and saved to an output file in XML format. A file chooser dialog is presented to the user to choose the output file. The file is useful when submitting bug reports about the Decompiler as it is generally much smaller than the entire Program and only contains information specific to the function. Information is generated by performing the full decompilation of the function and collecting all the data and annotations required during the process, including instruction bytes, symbols, data-types, and other settings affecting decompilation.

#### Graph Data Flow

This action is located in the drop-down menu on the right side of the Decompiler window tool/title bar.

Generate a data flow graph based upon the results in the active Decompiler window, and render it using the current Graph Service.

#### Graph Control Flow

This action is located in the drop-down menu on the right side of the Decompiler window tool/title bar.

Generate a control flow graph based upon the results in the active Decompiler window, and render it using the current Graph Service.

### Mouse Actions

#### Left-Click

Moves the Decompiler window cursor and highlights the token. Within the main window, if a token has a machine address associated with it, a left-click generates a navigation event to that address, which may cause other windows to display code near that address (see ).

Selecting a '(' or ')' token causes it and its matching parenthesis to be highlighted along with the entire expression they surround.

Selecting a '{' or '}' token causes it and its matching brace to be highlighted.

#### Right-Click

Moves the Decompiler window cursor, highlights the token, and brings up the menu of context-sensitive actions. Any highlighting and navigation is identical to a left-click. The menu actions presented depend primarily on the token type and are tailored to the context at that point in the code.

#### Double-Click

Navigates based on the selected symbol or other token (see below). If the selected token represents a formal symbol, such as a function name or a global variable, double-clicking causes a navigation event to the address associated with the symbol.

This action is performed by clicking twice on the desired token with the left mouse button.

Function Symbols

  Double-clicking a called function name causes the window itself to navigate away from its current function to the called function, triggering a new decompilation if necessary and changing its display.

Global Variables

  Double-clicking a global variable name does not have any effect on the Decompiler window itself, but Listing or other windows may navigate to the storage address of the global variable.

Constants

  Double-clicking a token representing a constant causes the constant to be treated as an address, and a navigation event to that address is generated. The Decompiler window itself navigates depending again on whether the address represents a new function or not.

Labels

  Double-clicking the label within a goto statement causes the window to navigate to the target of the goto, within the function. The cursor is set and the window view is adjusted if necessary to ensure that the target is visible.

Braces

  Double-clicking a '{' or '}' token, causes the window to navigate to the matching brace within the window. The cursor is set and the window view is adjusted if necessary to ensure that the matching brace is visible.

  Braces may also be navigated via the keyboard.

#### Ctrl-Double-Click

Opens a new Snapshot window, navigating it to the selected symbol. This is a convenience for immediately decompiling and displaying a called function in a new window, without disturbing the active window. The behavior is similar to the Double-Click action, the selected token must represent a function name symbol or possibly a constant address, but the navigation occurs in the new Snapshot window.

This action is performed by clicking twice on the desired token with the left mouse button, while holding down the Ctrl key.

#### Ctrl-Shift-Click

Generates a navigation event to the address, within the current function, associated with the clicked token. This allows Snapshot windows to do basic cross-highlighting in the same way as the main Decompiler window. A ctrl-shift-click causes Listing and other windows to navigate to and display the same portion of code currently being displayed in the Snapshot window (see ).

This action is performed by clicking on the desired token with the left mouse button, while holding down both the Ctrl and Shift keys.

#### Middle-Click

Highlights every occurrence of a variable, constant, or operator represented by the selected token, within the Decompiler window. There are actions available from the popup menu and from the keyboard to navigate to each highlighted token.

### Pop-up Menu and Keyboard Actions

Almost all the actions described in this section can be activated from the menu that pops up when right-clicking on a token within the Decompiler window. The pop-up menu is context sensitive and the type of token in particular (see ) determines what actions are available. The token clicked provides a local context for the action and may be used to pinpoint the exact variable or operation affected.

Many of the actions have a key binding, which, if it exists, will be listed in the pop-up menu. If the key binding is used to activate the action, local context is determined by the current cursor position. Key bindings can be reassigned from the Key Bindings section of the Tool Options Dialog.

#### Adjust Pointer Offset

Create a pointer with an offset into its underlying data-type and apply it to the selected variable.

The action is available on variable tokens that the Decompiler has already determined are pointers, and is designed to create an offset pointer, which is a typedef with its component offset attribute set (See ). It brings up a dialog that allows the user to select:

- An underlying data-type for the new pointer
- A byte offset (relative to the start of the underlying data-type)
- A name for the new pointer data-type

If the Decompiler determines that the selected variable points into a known structure, this information is used to prepopulate the dialog, with the structure used as the underlying data-type.

Clicking OK in the dialog immediately creates the new pointer data-type and attaches it to the selected variable, triggering a new decompilation. The annotation may reveal new field accesses or other markup associated with the underlying data-type, which will be immediately visible once decompilation completes.

If the user selects the name of an offset pointer that already exists and its other properties match the dialog, the existing pointer will be used to complete the action, rather than creating a new data-type. If an unrelated data-type already exists with the selected name, the action cannot be completed and the dialog will display a warning.

If the offset pointer already exists but its offset does not match the value specified in the dialog, the user is given the option of changing the existing data-type's offset. Confirming this change alters the existing data-type, which may affect analysis of other unrelated parts of the program that use it.

Once an offset pointer exists, either by invoking this action or by creating it manually (see Pointer-Typedef Settings), it can be applied to variables like any other data-type, either through the Listing window or using the action in the Decompiler window.

#### Auto Create Structure

Automatically create a structure data-type for a selected variable based on its use within the current function and possibly child functions.

The structure definition is filled in by examining how the variable is used, assuming it is a pointer to the structure, tracing data flow to all the expressions the variable is used in. LOAD and STORE operations trigger new fields and additive offsets are traced to calculate the offset of the fields within the structure definition.

Once the new structure is created, the selected variable is retyped to be a pointer to the structure. Within the window, the function is decompiled again and references to new fields in the structure should be immediately apparent. These can be renamed or retyped from the window to further refine the new structure definition (see ).

Auto Fill in Structure

  If the selected variable is already a pointer to a structure, this action fills in new information about the structure on top of the existing structure definition. Depending on how the pointer is used in the current function, new fields may be added and the data-type of undefined fields may be changed, but other existing parts of the structure definition are preserved.

Auto Fill in Class Structure

  If the selected variable is the this parameter for a class method, the menu title for this action reflects this, but the action is the same. The class's structure definition is filled in with any new information.

#### Comments

Set or change a comment at the address of the selected token.

These actions bring up the general Comment dialog (see Comments), which associates the comment with a specific address in the Program. For comment actions in the Decompiler, this address is of the machine instruction most closely linked to the selected token. Any comments generated from a Decompiler window will be visible in Listing and other windows viewing the same section of code.

A Decompiler window can display all comment types, but this may be affected by the Display options (see ).

Set Plate Comment...

  Brings up the dialog for setting or editing a Plate comment.

Set Pre Comment...

  Brings up the dialog for setting or editing a Pre comment.

Set...

  Brings up the dialog for setting or editing a comment based on the selected token. A Plate comment is edited if the token is part of the function's header. A Pre comment is edited otherwise.

#### Commit Local Names

Commit the names of any local variables discovered during the Decompiler's analysis to the Program database as new Variable Annotations. The recovered data-type is not committed as part of the annotation, only the name and storage location.

Parameters are not affected by this command (see ). The purpose of the command is to synchronize the local variables in the Decompiler's view of a function with the formal Variable Annotations in the disassembly view, without otherwise affecting the decompilation. After executing this command, additional changes to local variables can be performed directly on the corresponding annotations displayed in Listing windows, using various methods (see ). Data-types are not forced for new annotations, they are created with an undefined data-type, which allows the Decompiler to refine its view of the variable's data-type as new information becomes available (see ).

#### Commit Params/Return

Commit the Decompiler's analysis of the input parameters and return value of the current function as annotations to the Program database.

In the absence of either imported or user-defined information about a function's prototype, the Decompiler performs its own analysis of what the prototype is, determining the storage location and data-type of all parameters and the return value. This action commits this analysis permanently for the current function displayed in the window, creating a matching Variable Annotation for each input parameter and the return value. The new annotations will be displayed in a Listing window as part of the function header, and the action effectively synchronizes the disassembly view and Decompiler's view of the function prototype.

Committed prototype information is used both when decompiling the function itself and when decompiling other functions that call it. The committed annotations are forcing on the Decompiler (see ), and it will no longer perform prototype recovery analysis for that function. The Decompiler assumes the committed parameters, and only the committed parameters, exist and will not modify their data-types, with the exception of parameters that are explicitly marked as having an undefined data-type. The user must manually modify individual variables or clear the entire prototype if they want a change (see ).

#### Convert

Change the displayed encoding for the integer or character constant under the cursor.

Various encodings are possible.

Binary: | 0b01100001
Decimal: | 97
Hexadecimal: | 0x61
Octal: | 0141
Char: | 'a'

This command primarily targets a constant token in the Decompiler window, but if there is a scalar operand in an instruction that corresponds with the selected constant, the same conversion is also applied to the scalar in any Listing window. This is equivalent to selecting the Convert command from a Listing window. There may not be a scalar operand directly corresponding to the selected constant, in which case the conversion will be applied only in the Decompiler window.

The data-type of the selected token is not changed by the action, and it retains its meaning in the decompiler output. This slightly limits the possible conversions as signed values cannot be forced into an unsigned representation, and vice versa.

The constant's encoding can be changed by selecting a different Convert command, or it can be returned to its default encoding by selecting the command.

#### Copy

Copy selected code from the Decompiler window into the clipboard.

This is part of the standard copy capabilities for all Ghidra windows and is suitable for copying (sections of) Decompiler output into other documents.

#### Edit Data Type

Bring up a dialog for editing the definition of the data-type under the cursor.

The cursor must be on the data-type name token, not on a variable or other syntax. The action is only available for structures and unions, which will bring up the Structure Editor, and for enumerations, which will bring up the Enum Editor.

Any change to the definition of the data-type is automatically incorporated by the Decompiler into its output (see ).

#### Edit Function Signature

Bring up a dialog for editing the prototype of a selected function and other details about how it passes parameters.

The action is available from any token in the Decompiler window. Most tokens trigger editing of the current function itself, but a called function can be edited by putting the cursor on its name specifically.

The dialog provides detailed control over elements like

- Parameters - including name, data-type, and storage
- Return Type - including data-type and storage
- Variable Arguments and
- Inlining

See documentation for the Function Editor Dialog. The Decompiler automatically incorporates any changes into its output.

#### Find...

Search for strings within the active window, in the current Decompiler output.

The command brings up a dialog where a search pattern can be entered as a raw string or regular expression. The search is performed directly on the text of the decompiled function, from the current cursor; forward each time the Next button is hit, or backward for the Previous button. Any match is highlighted in the window, and the cursor is set to the start of the match.

#### Force Field

Force the Decompiler to assume a specific read or write to a variable, with a union data-type, is referring to a user selected field.

A union data-type overlays multiple other data-type interpretations (fields) on top of one variable; any one of which may be active at a point where the variable is accessed. The Decompiler automatically selects which field it thinks is being referenced (See ). But this action allows the user to force the Decompiler to use a particular field.

The cursor must be on the token currently representing the union field to be changed. The action brings up a dialog with a drop-down menu of the possible fields that can be forced. A field must be compatible with the selected access or it will not be listed in the menu. This usually means that the data-type of the field must be the same size as the read or write being performed. The menu option `(no field)` may also be available, which if selected, indicates that the Decompiler should treat the read or write as accessing the union as a whole. Its also possible that no other field is possible but the current one. In which case, the dialog will display a warning message and contain no drop-down menu.

Selecting a menu option and clicking OK completes the action. Subsequent decompilation should show the new field at the selected access point, and the data-type associated with the selected field will likely propagate further across the function, possibly triggering substantial changes to the output.

If there is more than one access to the same variable with a union data-type, each representative field token can be forced to a new field individually.

#### Go To Next/Previous Brace

These actions are available from the keyboard, with no equivalent pop-up menu entry. Shift-Open Bracket will go to the previous enclosing open brace. Shift-Close Bracket will go to the next enclosing closing brace. These key bindings can be changed via the Tool Options Dialog.

Paired braces can also be navigated by double-clicking.

#### Go To Next/Previous Highlight

These actions are available from the popup menu and keyboard. Only tokens highlighted from the middle-mouse will be navigated. Shift-Comma will go to the previous highlighted token. Shift-Period will go to the next highlighted token. These key bindings can be changed via the Tool Options Dialog.

#### Highlight

All these actions highlight a specific set of variable tokens tracing the data flow of the selected variable within the current function, defined as the directed flow of data from input variables through operations that manipulate their value to their output variables. The operations and variables chain together to form data-flow paths.

Def-Use

  Highlight the single token where the selected variable was last written (def), and highlight all the tokens where that single value is read (use). The written token, generally where the variable is on the left-hand side of an assignment expression, is highlighted in a different color. If the variable is written on multiple merging control-flow paths, no written token is highlighted.

  In the following example, the token representing the first write to the variable a is selected when Def-Use is chosen.

Forward Slice

  Highlight all variable tokens where the value at that point in the function is directly affected by the value at the selected variable token. A token is highlighted if there is a direct data-flow path starting from the selected point and ending at the token. A call operation is not considered a direct data-flow path from its input parameters to its output value.

  In the following example, the token b, the output of max_alpha, is selected when Forward Slice is chosen.

Backward Slice

  Highlight all variable tokens where the value at that point in the function directly affects the value at the selected variable token. A token is highlighted if there is a direct data-flow path starting from the token and ending at the selected point. A call operation is not considered a direct data-flow path from its input parameters to its output value.

Forward Operator Slice

  Highlight every operator token that manipulates a value directly affected by the value at the selected variable token. Along each direct data-flow path that starts at the selected point, each token representing an operation is highlighted, along with any explicit variable read or written by the operation. A call operation is not considered a direct data-flow path from its input parameters to its output value. This is an alternate presentation of the slice displayed by the Forward Slice action.

Backward Operator Slice

  Highlight every operator token that manipulates a value that directly affects the value at the selected variable token. Along each direct data-flow path that ends at the selected point, each token representing an operation is highlighted, along with any explicit variable read or written by the operation. A call operation is not considered a direct data-flow path from its input parameters to its output value. This is an alternate presentation of the slice displayed by the Backward Slice action.

#### Secondary Highlight

A secondary highlight is a semi-permanent token highlight in the Decompiler window that, unlike normal highlights, will not go away as the user clicks other tokens. The color and text being highlighted is controlled by the user and will persist for for the duration of the Ghidra session or until the user explicitly removes the highlight.

Set Highlight

  Apply a secondary highlight to all text matching the text of the token under the cursor. A color is chosen randomly for the Ghidra session. If the same highlight is removed and then reactivated later in the session, the same color will be used.

Set Highlight...

  Apply a secondary highlight to all text matching the text of the token under the cursor, as in the Set Highlight action above. A Color Chooser dialog is shown allowing the user to select the specific color for the highlight. The dialog is initialized with a random color or with the color previously applied to the same token.

Remove Highlight

  Remove the existing secondary highlight applied to the token under the cursor. Other highlights are not affected.

Remove All Highlights

  Remove all secondary highlights in the current function. Highlights in other functions are not affected.

#### Override Signature

Override the function prototype corresponding to the function under the cursor.

This action can be triggered at a call site, where the function being decompiled is calling into another function. Users must select either the token representing the called function's name or one of the tokens representing the function pointer at the call site. The action brings up a dialog where the function prototype corresponding to the call site can be edited. The dialog provides fine-grained control of the return data-type along with the name and data-type of each input parameter. The function prototype properties Calling Convention, In Line, and No Return can also be set (see ).

Confirming the dialog forces the new function prototype on the Decompiler's view of the called function, but only for the single selected call site.

This action is suitable for either indirect calls or direct calls to functions taking a variable number of arguments; situations where a complete description of all parameters is not available. For direct calls with a fixed number of arguments, it is almost always better to provide parameter information by setting the function's prototype directly (see the command). In this situation, the "Override Signature" command is still possible, but it will bring up a confirmation dialog.

#### Edit Signature Override

Edit the overriding function prototype applied previously to the called function under the cursor.

This action can only be triggered at call sites with an existing signature override. As with the Override Signature command, users must select either the token representing the called function's name or the tokens representing the function pointer at the call site. The action brings up a dialog where the user can edit the current overriding function prototype.

#### References

##### Find Uses of <data-type>

Calculate locations in the Program that reference the data-type of the token under the cursor. Results are collected in a Location References Dialog, which displays a row for each reference with its address and other context.

Uses (references) specifically are to variables that have been assigned the data-type. References to parameters and global variables are always listed. If the Dynamic Data Type Discovery option is on (see To Find Location References to Data Types), the Decompiler's propagation analysis is invoked on all functions to discover local variables as well.

##### Find References to <function/global variable>

Display locations in the Program that reference the function or global variable associated with the token under the cursor. Results are collected in a Location References Dialog, which displays a row for each reference with its address and other context.

In the case of a function, references include both instructions and data referring to the entry point address of the function.

##### Show References to <address>

Display locations in the Program that reference the address associated with the token under the cursor. Results are collected in a Location References Dialog, which displays a row for each reference with its address and other context.

The selected address is of the instruction most closely associated with the variable or operator represented by the token.

#### Remove Convert/Equate

Remove the display conversion or equate from the constant under the cursor.

The selected constant must have had either a or a command applied to it. After applying this command, the conversion is no longer applied, and the selected constant will be displayed using the decompiler's default strategy, which depends on the data-type of the constant and other display settings (See ).

#### Remove Signature Override

Remove the overriding function prototype applied previously to the called function under the cursor.

This action can only be triggered at call sites, where an overriding prototype was previously placed by the command. As with this command, users must select either the token representing the called function's name or the tokens representing the function pointer at the call site. The action causes the override to be removed immediately. Parameter information will be drawn from the Decompiler's normal analysis.

#### Remove Label

Remove the label corresponding to the token under the cursor.

A label can be removed by triggering this action while the corresponding label token is under the cursor. For more on removing labels, see Removing a Label.

The change will be immediately visible across all references to the label (including in any Decompiler, Listing, and Functions windows).

#### Rename Function

Rename the function corresponding to the token under the cursor.

The current function can be renamed by selecting the name token within the function's declaration at the top of the Decompiler window, or individual called functions can be renamed by selecting their name token within a call expression. This action brings up a dialog containing a text field prepopulated with the name to be changed. The current namespace (and any parent namespaces) is presented in a drop-down menu. Editing the text field changes the base name of the function, and selecting within the drop-down menu allows the function to be moved into a parent namespace.

A new or child namespace can be specified by prepending the base name with the namespace using the C++ "::" delimiter characters. Any namespace path entered this way is considered relative to the namespace set in the drop-down menu, so the Global namespace may need to be selected if the user wants to specify an absolute path. If any path element of the namespace does not exist, it is created.

The change will be immediately visible across all references to the function (including in any Decompiler, Listing, and Functions windows).

#### Rename Field

Rename the field currently under the cursor within its structure data-type definition.

The action brings up a dialog prepopulated with the current name of the field. Editing and confirming this dialog immediately changes the field's name in its corresponding structure definition. The dialog enforces unique field names.

If the initial name looks like `field_0x..`, it may be that the field offset was discovered by the Decompiler, and the field does not exist in the structure definition. In this case, a new field is created at that offset, with the new name and a data-type of undefined.

The change to the definition is visible globally throughout the Program, anywhere the data-type is referenced. Decompilation is triggered again to incorporate the new name, but the output is otherwise unaffected.

Within a Decompiler window, field name tokens are presented in context, showing how they are used within the code flow of the current function. Combined with and , this action allows a structure to be created and filled in based on this context.

#### Rename Global

Rename the global variable corresponding to the token under the cursor.

This action brings up a dialog containing a text field prepopulated with the current name of the variable. The current namespace (and any parent namespaces) is presented in a drop-down menu. Editing the text field changes the base name of the variable, and selecting within the drop-down menu allows the variable to be moved into a parent namespace.

A new or child namespace can be specified by prepending the base name with the namespace using the C++ "::" delimiter characters. Any namespace path entered this way is considered relative to the namespace set in the drop-down menu, so the Global namespace may need to be selected if the user wants to specify an absolute path. If any path element of the namespace does not exist, it is created.

The change will be immediately visible across all references to the variable, including in Decompiler and Listing windows. A new decompilation is triggered to incorporate the new name, but the output is otherwise unaffected.

#### Rename Label

Rename the label corresponding to the token under the cursor.

A label can be renamed by triggering this action while the corresponding label token is under the cursor. This action brings up the Edit Label Dialog.

The change will be immediately visible across all references to the label (including in any Decompiler, Listing, and Functions windows).

#### Rename Variable

Rename the local variable or parameter currently under the cursor.

The action brings up a dialog prepopulated with the current name of the variable. Editing and confirming this dialog immediately changes the name, unless there is a conflict with another variable.

Decompilation is triggered again to incorporate the new name, causing local variable declarations to be reordered and line breaks to change, but otherwise the output is unaffected.

Local variables and parameters presented by the Decompiler may be invented on-the-fly and don't necessarily have a formal annotation in Ghidra (see ). Performing this action on a variable will create an annotation if one didn't exist previously, which will generally be visible as part of the function header in any Listing window. A new annotation will not commit the data-type of the variable, and data-types applied later, and elsewhere in the function, can still propagate into the variable.

Performing this action on a function parameter causes a formal annotation to be created for all parameters, although the names of any other parameters will not be changed.

#### Retype Field

Change the data-type of the field currently under the cursor within its structure data-type definition.

The action brings up a dialog prepopulated with the current data-type associated with the field. The user can select any fixed length data-type in the Program, although selecting a larger data-type may cause an error if there is not enough room for it with other existing fields. Editing and confirming this dialog immediately changes the corresponding data-type definition.

The change to the definition is visible globally throughout the Program, anywhere the data-type is referenced, and is forcing on the Decompiler (see ). Decompilation is triggered again, and the new data-type is propagated from the point of the field reference(s). Changes to the output may be large and indirect.

#### Retype Global

Change the data-type of the global variable currently under the cursor.

This action brings up a dialog prepopulated with the current data-type of the variable. The user can select any fixed length data-type in the Program that matches the size of the variable. Editing and confirming this dialog immediately changes the data-type.

The change is visible globally throughout the Program, anywhere the variable is referenced, and is forcing on the Decompiler (see ). Decompilation is triggered again, and the new data-type is propagated from the variable reference(s). Changes to the output may be large and indirect.

#### Retype Return

Change the data-type of the current function's return value.

This action is only available from the data-type token in the function declaration, at the top of the Decompiler's output. It brings up a dialog prepopulated with the current data-type returned by the function. The user can select any fixed length data-type in the Program. Editing and confirming this dialog immediately changes the data-type. If an annotation for the return value (named `<RETURN>`) did not exist previously, one is created.

As input parameter annotations and the return value annotation must be committed as a whole (see the discussion of function prototype's in ), if no prototype existed previously, this action also causes variable annotations for all input parameters to be created as well. In this situation, the action is equivalent to , and a confirmation dialog comes up to notify the user.

Setting a data-type on the return value using this action affects decompilation for the function itself and, additionally, any function that calls this function. Within a calling function, the Decompiler propagates the data-type into the variable or expression incorporating the return value at each call site.

#### Retype Variable

Change the data-type of the local variable or parameter currently under the cursor.

This action brings up a dialog prepopulated with the current data-type of the variable. The user can select any fixed length data-type in the Program that matches the size of the variable. Editing and confirming this dialog immediately changes the data-type.

The change to the data-type is forcing on the Decompiler (see ). Decompilation is triggered again, and the new data-type is propagated from the variable reference(s). Changes to the output may be large and indirect.

Local variables and parameters presented by the Decompiler may be invented on-the-fly and don't necessarily have a formal annotation in Ghidra (see ). Performing this action on a variable will create an annotation if one didn't exist previously, which will generally be visible as part of the function header in any Listing window.

Performing this action on a function parameter causes a formal annotation to be created for all parameters to the function, and the number of parameters and their memory locations become fixed. If the annotation of another parameter did not exist previously, then its data-type is not forced by this action.

Data-type information applied to parameters using this action is especially impactful because it affects decompilation for the function owning the parameter and, additionally, any function that calls this owning function.

#### Set Equate...

Change the display of the integer or character constant under the cursor to an equate string.

An equate is a descriptive string associated with a specific constant value, which is managed globally for a Program by the Equate plug-in (See Equates).

The Set Equate command, brings up a dialog listing other equates that have previously been associated with the selected constant. The user can choose an equate from this list or define a new equate for the constant by typing in the text field at the top of the dialog. Alternately, the text field can be used as a filter to narrow down possibilities prior to selecting from the list. Clicking OK, completes the action, and the selected equate is substituted for its constant.

This command primarily targets a constant token in a Decompiler window, but if there is a scalar operand in an instruction that corresponds with the selected constant, the same equate is also applied to the scalar in any Listing window. This is equivalent to selecting the Set Equate command from a Listing window. There may not be a scalar operand directly corresponding to the selected constant, in which case the equate will be applied only in the Decompiler window.

Once an equate is applied, the constant can be returned to its default display by selecting the command.

#### Split Out As New Variable

Split a high-level variable so that the selected token becomes a new variable with the smallest possible range.

The Decompiler defines high-level variables in terms of varnodes that are merged together to produce the final variable. Some merging is speculative, which reduces the number of variables overall, but is not strictly necessary for valid decompilation. The merged variable can be represented with two or more variables that have a smaller range (see the documentation on ).

This command is only available if the selected token is part of a high-level variable that has been speculatively merged. The part of the variable that is directly represented by the token is split out as its own variable, retaining the name of the original variable. Any other pieces become a separate variable with a new name.