> For the complete documentation index, see [llms.txt](https://docs.hex-rays.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hex-rays.com/release-notes/9_5.md).

# IDA 9.5

## IDA 9.5

**IDA 9.5.261026**

![](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-6100a11b006344467b9badbb90eac0ccf4b1d0bd%2F95.png?alt=media)

Welcome to the IDA 9.5 release highlights. You can get your 9.5 installers in the [Download Center](https://my.hex-rays.com/dashboard/download-center/installers/release) of My Hex-Rays portal.

## What's in this release

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><a href="#highlights"><strong>Highlights</strong></a></td><td>The marquee features: the new Dalvik, TriCore and Hexagon decompilers, decompiler bitfield support, a much stronger AVX/SSE pipeline, the Apple kernelcache loader, verbatim names, FLIRT 2.0, smarter switch-case recovery, and recursive "Create C file" export.</td></tr><tr><td><a href="#hll"><strong>Higher-Level Language Support</strong></a></td><td>Loading Go binaries with corrupt or obfuscated metadata, and the Rust ABI extended to ARM[64], MIPS, PPC and RISC-V.</td></tr><tr><td><a href="#decompiler"><strong>Decompiler</strong></a></td><td>Jump to function-pointer targets, register-variable splitting, scattered pairs, better x87 handling, stripped-Swift recovery, and many output-quality improvements.</td></tr><tr><td><a href="#disassembler"><strong>Disassembler</strong></a></td><td>Register values tracked across loops, ARC/Hexagon/MIPS R6 work, more Armv9 extensions, broad game-console support (PS3, Xbox 360, Wii U, PSP), and a new WebAssembly loader and disassembler.</td></tr><tr><td><a href="#analysis"><strong>Analysis &#x26; Kernel</strong></a></td><td>Correct exception-handling stack levels, robust try blocks, and guards against pathological binaries.</td></tr><tr><td><a href="#loaders"><strong>Loaders</strong></a></td><td>A new UEFI plugin and loader that read whole firmware images and make known protocol calls decompile to readable code, plus transparent zstd decompression, VDEX and DEX 040 support, and expanded Mach-O kernelcache handling.</td></tr><tr><td><a href="#typesystem"><strong>Type System</strong></a></td><td>Clang is the new default parser, with version-matched XNU type libraries for Apple Silicon macOS kernels.</td></tr><tr><td><a href="#debuginfo"><strong>Debug Info, Demangling and Exception Handling</strong></a></td><td>Swift 6 demangling, better DWARF and PDB handling, and Rust type recovery.</td></tr><tr><td><a href="#uiux"><strong>UI &#x26; UX</strong></a></td><td>Qt 6.12 LTS, a new HTML listing renderer, a tightly-linked Pathfinder and Xref graph, and a reworked quick filter.</td></tr><tr><td><a href="#debuggers"><strong>Debuggers</strong></a></td><td>A remote debug server hardened against a malformed client request that could crash it.</td></tr><tr><td><a href="#flirt"><strong>FLIRT &#x26; FLAIR</strong></a></td><td>FLIRT 2.0 signatures, byte-range patterns, and refreshed MSVC runtime coverage.</td></tr><tr><td><a href="#performance"><strong>Performance &#x26; Resource Consumption</strong></a></td><td>Less memory and fewer stalls on large binaries: DWARF, dyld shared caches, RTTI and the decompiler.</td></tr><tr><td><a href="#sdk"><strong>Configuration, IDAPython, SDK &#x26; API</strong></a></td><td>Installation manifests for every extension kind, plus new listing-export, class, license-inspection and synthetic-string APIs.</td></tr><tr><td><a href="#network"><strong>Network &#x26; Security</strong></a></td><td>Clear answers when a license, Lumina or Vault server misbehaves, no more freezes, and hardened Linux builds.</td></tr></tbody></table>

## Highlights <a href="#highlights" id="highlights"></a>

{% hint style="info" %}
**Update your license file**

To unlock all the new decompilers in **IDA Home** and **IDA Ultimate** 9.5, download your updated license file from the [Customer Portal](https://my.hex-rays.com/dashboard/licenses) and replace your current one.
{% endhint %}

### New Decompiler: Dalvik

IDA now decompiles Android DEX bytecode into Java pseudocode. It is built on a typed model of the DEX file: classes, fields, methods and parameters are real entities that can be renamed and retyped, and every edit propagates through the pseudocode.

The class view is where you work. Tab switches between it and the disassembly. It lists the program's classes and shows each declaration with its fields and methods, and Ctrl+Shift+F6 or Ctrl+double-click in the class tree opens another class view. It has the usual pseudocode actions: comments, renaming (locals, arguments, labels, fields, methods), "Set type" in Java syntax, collapse, invert if, hide casts, map variable, cross-references and synchronization with other views.

* In multidex applications, calls reach the method in the other dex file, and virtual calls also reference the overrides in subclasses.
* Methods with optimized (odex) bytecode are decompiled too.
* Original names are restored from Kotlin metadata, serializer annotations and DEX debug info, when the file still carries them.

![The class view on a multidex sample app](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-368e3f19b0b5c9b0768313438d8a2ff5fbc38e44%2Fdalvik-class-view.webp?alt=media)

The output reads like the source:

* String concatenation is shown as "a" + b rather than the StringBuilder chain that javac, kotlinc and d8 emit.
* Nested classes print as `Outer.Inner`. Declarations show generics, `@Annotations(...)` and anonymous classes as `new Type() { ... }`.
* Parameters are named from DEX annotations.
* Calls use the callee's declared type, so retyping a method updates its callers.
* `try`/`catch`/`finally` is reconstructed when possible, including nested blocks, catch-all handlers, `finally` blocks that end in `return` or `goto`, and `synchronized` blocks with several exits.

```java
static String looseOperands(int a, int b)
{
  return "and=" + (a & b) + " shl=" + (a << b);
}
```

A builder is left as it is when `+` would change the result (for example two numbers appended in a row) or when it lives across statements.

For scripts and plugins, a new language-neutral class API (`get_classes()`, `get_class_info()`, `render_class()`, `render_member()`, in C++ and IDAPython) has Dalvik as its first backend.

**Limitations:**

* `try`-with-resources is not reconstructed (the output is longer but correct)
* edits in the class view do not raise Hex-Rays pseudocode events
* the output is not always a valid Java (for example, it may contain `goto`s or comma operators)
* there is no special treatment for obfuscated files

### New Decompiler: TriCore

Infineon TriCore: the new `hextricore` plugin decompiles TriCore code. It supports `eabi` and `Tasking` ABI families.

* pointer arguments and return values are recognized in the A (address) registers. TriCore passes integers in d4-d7 and pointers in a4-a7, and each bank fills on its own, so the order of mixed arguments is not encoded in the binary; use "Set item type" (Y) to rearrange them
* `dvinit`/`dvstep`/`dvadj` division sequences of pre-1.6 cores, written out or as a `dvstep` loop (typical for Tasking), fold into a single division

![TriCore division example](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-7d7122ab4a8680570f68a61695962686a7684d0f%2Ftricore_divstep.png?alt=media)

### New Decompiler: Hexagon

Qualcomm Hexagon (QDSP6): the new `hexqdsp6` plugin decompiles DSP code. It models packet semantics (parallel reads, `.new` values, predication), hardware loops, compound branches and jump tables, floating point, and the scalar SIMD instructions; HVX vector and system instructions appear as intrinsics.

* every instruction of a packet reads its registers as of the packet start, `.new`/`.cur` operands see the packet's own results, and predicated instructions become conditional blocks
* variadic functions are recognized
* intrinsics use clang's `__builtin_HEXAGON_*` names, so their semantics can be looked up in `hexagon_protos.h`
* HVX vectors (`V0`–`V31`, `Q0`–`Q3`) are modeled as vector registers, and system, guest, cache and supervisor instructions appear as intrinsics

In `time()` below, `r16 = r0` copies the argument, not the call's result, because the call executes at the end of its packet; the store is guarded by `p0.new`, the comparison from the same packet:

![time() in the disassembly and the pseudocode, side by side](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-309bc3b56130c907065920332d5a8fd6c5f11a41%2Fhexagon-time-asm.webp?alt=media)

### Decompiler Support for Bitfields

Accesses to C [bitfield members](https://en.cppreference.com/c/language/bit_field) are shown as member accesses instead of shift and mask arithmetic: `(*(_DWORD *)&s >> 3) & 7` reads as `s.field`, and `*p = *p & 0xFFFFFF07 | (v << 3) & 0xF8` as `p->field = v` (once the types are correctly defined and applied). It covers every architecture supported by the decompiler, including the dedicated extract/insert instructions of ARM64, PPC, MIPS and RISC-V. It is enabled by default but can be turned off with "Decompile bitfield accesses" in **Edit > Plugins > Hex-Rays Decompiler Options > Options 2**

Most patterns used by popular compilers are handled. For example, the non-obvious xor toggle from MSVC:

```c
struct s4 { unsigned a : 4; unsigned b : 4; unsigned rest : 24; };
void inc_a(struct s4 *p) { p->a++; }
// 9.4
 *(_DWORD *)p ^= ((unsigned __int8)*(_DWORD *)p ^ (unsigned __int8)(*(_DWORD *)p + 1)) & 0xF;
// 9.5
++p->a;
```

Other recognized shapes:

* reads scaled by a power of two (the mask gets scaled too)
* fields extracted from a copy of the unit loaded into a register
* a field in the top bit tested by a signed comparison,
* an access narrower than the unit

```c
// 9.4
if ( ControlPc >= ((*((_DWORD *)v1 + 1) >> 6) & 0xFFFFFC) + v1->FuncStart )
v16 = *((_DWORD *)FunctionEntry + 1);
if ( (v16 & 0xC0000000) == 0x80000000 )
if ( *((int *)this->m_pDevice + 5442) < 0 )
if ( (*((_BYTE *)Material + 720) & 1) == 0 )
// 9.5
if ( ControlPc >= 4 * v7->FuncLen + v7->FuncStart )
if ( FunctionEntry->Flags == 2 )
if ( this->m_pDevice->m_TimingCaptureActive != 0 )
if ( Material->bUseOneLayerDistortion == 0 )
```

A store that packs several fields of one unit decomposes into per-field assignments; the same field compared or combined across two objects shows both members; a masked compound update with a variable operand folds:

```c
// 9.4
U = C | (v1 << s1) | (v2 << s2);
(a.type ^ b.type) & MASK
U ^= V & MASK
// 9.5
x.f1 = v1; x.f2 = v2;
a.f ^ b.f
x.f ^= V
```

The bit allocation order defauls to the same direction as byte order, but can be fliped for specific types. This is a common situation in Xbox 360 binaries, which use litte-endian bitfield order for GPU registers or some kernel structures inherited from the Windows kernel. If needed, `#pragma bitfield_order(lsb_to_msb)` or `__invbf` specifier can be used to mark such types.

When PDB with full type info is available, it is used to detect the bit order:

```c
// 9.4: LSB order (wrong default for BE binary)
struct IMPORT_OBJECT_HEADER { 
  ... 
  unsigned __int16 Reserved : 11;
  unsigned __int16 NameType : 3;
  unsigned __int16 Type     : 2; 
};
// 9.5: same order as winnt.h declares it
struct IMPORT_OBJECT_HEADER { 
  ... 
  unsigned __int16 Type : 2;
  unsigned __int16 NameType : 3;
  unsigned __int16 Reserved : 11;
};
```

### Better SSE/AVX/AVX2/AVX-512 Support in the Disassembler and Decompiler

* x86/x64: loads and stores wider than 16 bytes are shown as plain C assignments instead of SSE/AVX load/store intrinsics, and `punpcklqdq` is shown as a move into the high half, so "Split expression" can split it; `movlhps`/`movhlps` are plain moves too

Where AVX code used to decompile to `__asm` blocks, the new `avxlifter` plugin turns AVX, AVX2, AVX-512 (F/CD/BW/DQ/VBMI/VNNI/BF16/FP16/VL) and VMX instructions into native microcode where the decompiler can reason about them, and into `_mm*_…` intrinsics on `__m128`/`__m256`/`__m512` values otherwise — masked EVEX merge/zero forms, gather/scatter, compress/expand and the opmask `k` registers included.

```c
// 9.4
void __fastcall q__mm256_add_pd(__int64 _RCX)
{
  __asm
  {
    vmovapd ymm0, ymmword ptr [rcx]
    vaddpd  ymm0, ymm0, ymmword ptr [rdx]
  }
}
// 9.5
__m256d __fastcall q__mm256_add_pd(__m256d *m1, __m256d *m2)
{
  return _mm256_add_pd(*m1, *m2);
}
```

* packed and/or/xor/andnot become C operators, so sign-flip and abs masks read as `a ^ signmask` and `a & absmask`, and `vxorpd x, x, x` is `0.0`
* scalar FMA and min/max become C math (`fminf`, `fmaxf`) instead of `_mm_*_ss` intrinsics

```c
vmaxss  xmm0, xmm0, xmm1
vminss  xmm0, xmm0, xmm2     ->  return fminf(fmaxf(a1, a2), a3);
vfmadd132sd xmm0, xmm1, xmm2 ->  return a1 * a3 + a2;
```

* intrinsics without side effects are marked pure, so dead vector computations are removed
* XMM, YMM and ZMM are modeled as views of one register, with legacy-SSE writes leaving the upper part intact; bogus undefined YMM variables are gone
* vector unions gain `__int128` members, which removes `*(_OWORD *)` casts
* SIMD loads, stores, `memcpy`/`memmove` and structure copies are plain assignments; no `_mm_loadu_si128`/`_mm256_storeu_ps` remain
* `tzcnt` is lifted to `__tzcnt()`
* string literals copied piecewise with `movups`/`movsd`/`mov`/`movzx`, UTF-16 and MSVC's mixed-width copies included, are recognized. This is analysis, not lifting, so it works without the plugin:

  ```asm
  ; 9.4
  movups  xmm0, cs:xmmword_140224F2C
  ; 9.5
  movups  xmm0, xmmword ptr cs:aErrorUnknownGl ; "ERROR: UNKNOWN GLFW ERROR"
  ```
* functions that align their frame pointer (`and rbp, -32`, typical for AVX code) have stack variables again, instead of `&v3 & 0xFFFFFFFFFFFFFFE0`

### Decompiler: Improved support for paired registers

On 32-bit platforms, 64-bit variables have to use register pairs for calculations. The decompiler already recognized variables placed in adjacent and aligned pairs (e.g. r0:r1 in ARM32). However, on high optimization levels compilers might resort to what we called "scattered" pairs: reversed pair (low half in R2, high half in R1), two non-adjacent registers (R3 and R12), or a register plus a stack slot. IDA 9.4 shows such values as two separate 32-bit variables joined by `__PAIR64__`, and you cannot retype either half to a 64-bit type. IDA 9.5 recognizes these pairs automatically and adds two commands to combine or split them by hand.

When the decompiler sees evidence that two halves form one value, it creates a single 64-bit variable with a scattered location. The recognition is deliberately conservative. It converts a pair only when the pair is used in a comparison, has one half on the stack, or occurs more than once. Ordinary register pairs that the decompiler already handled well, such as edx:eax on x86, are not affected. Names you gave to the halves carry over to the combined variable.

Example of a reversed register pair:

```c
//9.4
uint32_t retransmission_interval_d_tick_initial; // r2
uint32_t retransmission_interval_d_tick_initial_high; // r1
...
LODWORD(tcp_sub->retransmission_interval_d_tick_cur) = retransmission_interval_d_tick_initial_high;
HIDWORD(tcp_sub->retransmission_interval_d_tick_cur) = retransmission_interval_d_tick_initial;
p_retransmission_interval_d_tick_max = &tcp_sub->retransmission_interval_d_tick_max;
if ( __PAIR64__(retransmission_interval_d_tick_initial, retransmission_interval_d_tick_initial_high) < retransmission_interval_d_tick_maybe_initial_config )
  tcp_sub = (tcp_sub + 0x1D8);
...
  *p_retransmission_interval_d_tick_cur = retransmission_interval_d_tick_initial_high;
  *(p_retransmission_interval_d_tick_cur + 1) = retransmission_interval_d_tick_initial;

// 9.5
uint64_t retransmission_interval_d_tick_initial; // 0:r1.4,4:r2.4
...
tcp_sub->retransmission_interval_d_tick_cur = retransmission_interval_d_tick_initial;
p_retransmission_interval_d_tick_max = &tcp_sub->retransmission_interval_d_tick_max;
if ( retransmission_interval_d_tick_initial < retransmission_interval_d_tick_maybe_initial_config )
  tcp_sub = (tcp_sub + 0x1D8);
...
  *p_retransmission_interval_d_tick_cur = retransmission_interval_d_tick_initial;

```

For cases where such pairs are not detected automatically, the "Create scattered pair" action can be used to combine the two halves into one variable.

### Apple Kernel Cache Loader

IDA 9.5 does for Apple kernelcaches what 9.4 did for dyld shared caches: a kernelcache is a collection of KEXTs, and IDA now treats it as one rather than as a single large Mach-O. A boot KC and the system or auxiliary KCs linked against it are handled as one set.

![The KC Index: a KEXT mapped on demand shows as Loaded](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-3c81444330824df0f965495d82eda0f08366e03b%2Fkc_index.png?alt=media)

* the **KC Index** lists every KEXT and maps them on demand: the kernel up front, the rest as you reach them
* the IOKit C++ class hierarchy is reconstructed whenever possible, with the vtables and the virtual methods of each class
* classes the XNU type library only forward-declares (`SCSITask`, `IOServicePM`, …) are laid out from their recorded size, so their vtable slots get names
* **Locate > Symbol / String / Address** searches the whole cache, KEXTs you have not loaded included, and works on stripped caches too
* the Functions list has a folder per KEXT
* an example plugin extracts a KEXT, or a dyld cache image, to a standalone Mach-O

#### Typed Allocations (`kalloc_type`)

From iOS 16 and macOS 13 on, XNU allocates memory through `kalloc_type` descriptors that name the type being allocated. IDA uses them to type the allocations.

![The kalloc\_type views browser](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-33574868a974f6e74a2080b717d8d51ccef5795c%2Fkc_kalloc_views_browser.png?alt=media)

* the decompiler gives the result of an allocation the type it allocates
* types that no header declares, which is most of the kernel-internal ones, are laid out from their descriptor
* a new example plugin, `kalloc_type_views.py`, browses every typed allocation in the cache and lists where a type is allocated

### DriverKit Drivers

DriverKit drivers (`.dext`) are the user-space successors of KEXTs. IDA 9.5 recovers their classes, vtables and IORPC messages.

![The \_Dispatch of a third-party DriverKit driver, in the disassembly](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-b2816b295200ce12e412819640a6594676e5a572%2Fdriverkit_dispatch_disasm.png?alt=media)

![The same \_Dispatch, decompiled](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-f8d73b8f21cdd3a9a9207aee91fde7b2ec682e55%2Fdriverkit_dispatch_pseudo.png?alt=media)

* new DriverKit type libraries, one per SDK version, are picked automatically. They cover every device family; compared with the macOS SDK type libraries they add about 80 classes (audio, video, MIDI, SCSI, serial, block storage, networking).
* the classes a driver declares are recovered and typed, and their methods and vtables named. In a macOS 26 DriverKit shared cache, all 599 classes are typed correctly, up from 49.
* IORPC messages get their SDK names (`IOService_Start_ID` instead of `0AB6F76DDE6D693F2h`), in drivers and in arm64 kernelcaches, where the KEXTs' own symbols also name private messages no SDK declares.

### Verbatim Function and Type Names

Modern languages (Rust, Go, Swift, heavily-templated C++) name things with characters that are not valid C identifiers. IDA used to replace those with `_`, so names were hard to read and types could not be found by their real names. IDA 9.5 keeps symbol, type and member names verbatim, as they come from symbols, demanglers and debug info.

A Go function, in 9.4 and in 9.5:

![Go symbols in 9.4: runtime\_\_ptr\_Func\_FileLine](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-ece6844ba68850994a65ef16ec27fb866afe6ab6%2Fverbatim_golang_disasm_before.png?alt=media)

![Go symbols in 9.5: runtime.(\*Func).FileLine](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-2ff76baa87e303c5b6fca16c953dd428f5d02e5e%2Fverbatim_golang_disasm_after.png?alt=media)

Rust types from DWARF, in 9.4 and in 9.5:

![Rust types in 9.4: mut\_ref\_dyn\_core::fmt::Write, \_\_str](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-79a34e0830e4a1eb665ba769eb59cd80cc13513c%2Fverbatim_rust_localtypes_before.png?alt=media)

![Rust types in 9.5: \&mut dyn core::fmt::Write, &\[\&str\]](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-a3ad60cf683ece0db0c18fcf44b7275a78e9c15e%2Fverbatim_rust_localtypes_after.png?alt=media)

* new databases show demangled names by default
* qualified names such as `A::B::C` highlight and select as a single unit
* names that are not valid C can be typed in the type editor and the "Set type" dialogs, quoted with backticks

**Migration:** existing databases keep their current names. `GarbleNames` in `ida.cfg` brings the old behavior back for new databases.

### FLIRT 2.0

Classic FLIRT recognizes a library function from its bytes. The target of a call inside it is relocated by the linker, so FLIRT treats those bytes as a wildcard and forgets what they pointed to — and a helper that has no reliable signature of its own stays unnamed:

```c
void library_function()
{
  hidden_helper();   // call ?? ?? ?? ??  -- FLIRT 1 cannot name this
}
```

FLIRT 2.0 signatures (format v11) also record what each library module refers to. Once `library_function` is matched and its call lands at a certain address, IDA knows the function there is `hidden_helper`. After auto-analysis, a deferred pass names the functions reached from recognized code this way, and uses the same evidence to choose between byte-identical candidates.

Correctly named functions in a stripped, statically linked sqlite3:

| Runtime        |  9.4 |  9.5 |
| -------------- | ---: | ---: |
| glibc amd64    | 1279 | 1846 |
| glibc i386     | 1424 | 1826 |
| glibc arm64    | 1434 | 1815 |
| glibc armhf    |  776 | 1204 |
| glibc riscv64  |  288 |  933 |
| glibc s390x    | 1398 | 1739 |
| MSVC /MT x64   |  565 |  698 |
| MSVC /MT x86   |  458 |  561 |
| MSVC /MT arm64 |    0 |  753 |
| MSVC /MT arm   |    0 |  622 |

* 32-bit binaries of VC 14.39–14.52 are recognized, and the ARM and ARM64 MSVC runtime signatures cover VC11 through VC 14.52
* `main`/`wmain` and `WinMain`/`wWinMain` are told apart from evidence in the binary; startup signatures name the functions and data their entry module references (`___xc_a`, `__commode`, `__fmode`, ...)
* signatures can carry original, unmangled names: the Go runtime signatures keep `runtime.(*mheap).alloc` (the old mangled ones ship as `*_legacy.sig`)
* signatures load faster (bulk and buffered reads)

**Migration:** sigmake now always writes v11. IDA 9.5 reads older `.sig` files, but IDA 9.4 and earlier reject v11, so signatures built with the 9.5 FLAIR tools do not load in 9.4.

### More Precise Decompiler-Based Switch-Case Recovery

* switches that the compiler split across a binary-search dispatch are put back together: a switch nested under an equality or range guard is merged into its parent, and two switches separated by such a guard are combined into one
* a jump table built on a pivot-subtracted selector (`switch (x - C)`) is rebased onto the original value, so the real case labels are recovered
* switches are recovered better from if-chains, including dispatch trees whose cases fall through, and getopt-style trees whose arms leave through the enclosing loop
* cases are sorted by value, cases sharing a body are merged, and a case that only jumps into another case is folded into it

Compilers lower a sparse switch as a binary-search tree of comparisons, often against a pivot-subtracted copy of the selector, with the case bodies sharing tails through `goto`. All of that used to survive into the output. The recovery now runs at both levels: a microcode pass puts the jump table back on the original selector, and ctree passes fuse the fragments and restore the labels.

Shared case tails render as fall-through:

```c
// 9.4                        // 9.5
case 0u:                      case 0u:
  result = 1;                   result = 1;
  goto LABEL_3;               case 1u:
case 1u:                        ++result;
LABEL_3:                      case 2u:
  ++result;                     ++result;
  goto LABEL_4;               case 3u:
case 2u:                        ++result;
LABEL_4:                        break;
  ++result;
  ...
```

A jump table built on a pivot-subtracted selector dispatches on the same value as the surrounding comparisons again, so the fragments fuse and the real labels come back.

Dispatch trees whose case arms assign something and flow on into a shared tail are merged too — the commonest shape of all, and what makes a getopt loop mergeable. That is done only while the arm's original successor is the continuation kept after the merged switch, so the recovered switch computes what the original code did.

On every architecture — x86, ARM, MIPS, RISC-V, PPC, ARC, V850 and Dalvik — the decompiler now finds jump tables with its own data-flow analysis on the microcode instead of reusing the disassembler's switch information. Switches the disassembler missed ("switch analysis failed") are recovered, identical switches are merged, and many that used to decompile wrong are now correct:

```c
// 9.4
if ( v67 <= 8 )
  switch ( (unsigned int)(a3 + 7) >> 3 ) { ... }
// 9.5
switch ( v67 ) { ... }
```

* jump tables made of branch instructions (ARM `ADDLS PC, PC, R3,LSL#2` followed by `B case_n`, PPC/GHS tables) are recognized as switches, and Dalvik `packed-switch`/`sparse-switch` are built from their payload
* when the compiler reuses the selector's register for an offset copy (`v = x - C`), the comparisons are rewritten against the original variable and the dead offset chain is removed; recovered case labels keep their number format (enum, hex, char)
* where no range check can be found, the recovered switch shows `default: abort()`

### "Create C file" Decompiles a Function Together with Its Callees

**File > Produce file > Create C file...** (Ctrl+F5) now offers "Current function and its callees recursively" next to "All functions" (or the selection). Callees are decompiled first, from the leaves up, so every function is decompiled after the functions it calls, and their recovered prototypes improve the pseudocode of their callers.

* calls through `.plt` and stub thunks are followed into the real function; imports are skipped; the root function is always included and only its callees are filtered
* the dialog offers "Skip debugger segments", "Skip library functions" (on by default: only the non-library functions of the current module are included) and "Decompile to cache only" (no file is written; reports how many functions were decompiled); the choices are remembered between sessions
* the same is available without the dialog as "Decompile recursively" (**Edit > Other**, Ctrl+Shift+F5), and in batch mode with `-Ohexrays:-recursive`

### New Add-ons

### IDA MCP Add-on

A first-party, open-source MCP server that connects your AI agents to IDA, fully locally and across multiple databases at once.

### IDA Assist Add-on

Assist is an AI harness for reverse engineering, built into IDA. It works with any capable AI model, local or cloud, and combines the model with IDA's own analysis engines, emulation and an SMT solver to produce explainable results. It can analyze several databases at the same time.

### Malware Analysis Add-on

A new Hex-Rays add-on for malware analysts: one-click unpacking, safe emulation of suspicious code, and sandbox results shown right in the disassembly.

***

## Higher-Level Language Support <a href="#hll" id="hll"></a>

### The Disassembler and the Decompiler recover and show Swift Strings

The Swift compiler represents strings as two 64-bit immediates. A small string is embedded in the immediates themselves, a large literal is a tagged pointer, pointing at a fixed offset before its contents. This makes decoding Swift strings quite annoying, and typically required manual work, or writing a plugin. IDA 9.5 now has this logic built in, decodes the Swift strings, *and adds them to the String widget* (Shift-F12) for easier referencing. This mechanism is backed by our new Synthetic Strings API (see below) and is fully accessible to plugins. Here is an example of how the mechanism looks in real life (spot the decoded string at `0x220EA6B40`):

IDA 9.4:

```
0220EA6B30 MOV X8, #0x615373776F6C6C61
0220EA6B40 MOV X9, #0xEC000000203A6576
0220EA6B4C STP X8, X9, [SP,#0x80+var_78]
```

IDA 9.5:

```
0220EA6B30 MOV X8, #0x615373776F6C6C61
0220EA6B40 MOV X9, #isImmortal OR isASCII OR isSmall OR smallCount12 OR 0x203A6576 ; "allowsSave: "
0220EA6B4C STP X8, X9, [SP,#0x80+var_78]
```

Likewise, the decompiler now represents recognized strings as `Swift::String` entities, so the two components

```
v4._object = (void *)0xEE00444342413938LL;
v4._countAndFlagsBits = 0x3736353433323130LL;
```

now render as:

```
v4 = Swift::String("0123456789ABCD");
```

### Loading of Go Binaries with Corrupt/Obfuscated Metadata

IDA now loads Go binaries whose metadata has been damaged or obfuscated:

* the pclntab is found even when its magic is overwritten, its section is stripped or renamed, or it is embedded inside another segment
* the Go version is recovered when no build string survives
* functions and names are recovered in garble-obfuscated binaries
* Go 1.27 binaries are supported

### Rust ABI on ARM\[64]/MIPS/PPC/RISC-V

`CM_CC_RUST`, introduced for x86 in 9.4, is now implemented for ARM64, 32-bit ARM, MIPS (o32 and n64), PowerPC (32- and 64-bit) and RISC-V (32- and 64-bit), so Rust binaries on those targets get their real arguments and return values instead of guessed ones. Alongside it:

* string literals appear in the pseudocode instead of a raw address, and the string-slice type is named `&str`
* panic and abort helpers are recognized as non-returning
* the exception handling tables of Rust binaries are parsed
* zero-sized members and parameters (the unit type `()` included) are dropped from DWARF-recovered Rust types, and the hidden environment pointer of a closure is recovered
* Rust binaries are detected without DWARF, even when stripped — by `rust_eh_personality`, the `rustc-` markers in read-only data, and legacy or v0 mangling — and their functions default to `__rust` instead of `__fastcall`
* with DWARF, each function's convention is checked by lowering its DWARF signature under the Rust ABI: functions mislabeled `__usercall`/`__fastcall` become `__rust`, and `extern "C"` helpers wrongly marked `__rust` are corrected. The argument locations in clang/LLVM Rust DWARF are corrected too (reversed big-endian register pieces, mis-rebased stack slots)
* a packed or under-aligned aggregate return no longer loses all but its first field (x86/x64 included); sub-word arguments promoted into full registers, and mixed arguments whose stack part comes before the register part, are handled
* compiler-generated wrapper types for array arguments and returns get descriptive names (`_20_arr_int`) instead of `retval_<ea>`, so identical types are shared

### Minor Improvements

* golang: string literals are recognized in the microcode, so they appear in the pseudocode instead of a raw address
* golang: recognize runtime bounds-check panics as non-returning
* rust: panic and abort helpers are recognized as non-returning
* rust: more library functions that never return are recognized
* rust: the exception handling tables of Rust binaries are parsed
* rust: string literals are shown in the pseudocode instead of a raw address
* rust: the created string-slice type is named `&str`
* swift: recover string literals during auto analysis
* swift: recover string literals that only the decompiler sees
* swift: apply only complete prototypes to Swift functions
* swift: derive function and variable types from the demangle tree
* swift: show flags and metadata states of Swift runtime calls by name

### Bugfixes

* golang: negative `UnsafePoint` constants were shown as `0xFF` on unsigned-char targets
* golang: no type information was recovered from some big-endian binaries
* golang: no type information was recovered from some ppc64 binaries
* golang: an incomplete map type was recovered from Go 1.24 and later binaries
* rust: arm64: `u128` stack arguments were misaligned on macOS
* swift: wrong prototypes for Swift runtime calls taking or returning two-word values
* swift: calls lost String arguments when debug info described String

## Decompiler <a href="#decompiler" id="decompiler"></a>

### Jump to Function Pointer Struct Members

The Enter key and a double click on a called function pointer member now go to the function that the member points to, and not to the declaration of the member. A member of this kind is typically one entry of an operations or dispatch table that the program fills with function pointers. If the pseudocode names the object, IDA goes to the function of that object; if it does not, IDA offers the functions of all the objects that have the type. "Jump to structure definition" keeps its behavior, and a member that is not in a call keeps its behavior.

* the object can be a global, an array element with a constant index, a member of another structure or union, or a chain of these: `g_dev.ops.call()`, `g_tab[1].call()`
* when the object is not named, IDA scans every data item of the structure type: one target jumps directly, several open a "Possible callees of Type::member" chooser. Candidates come only from data items that have the structure type applied; for large arrays a cancellable wait box appears
* it works in the Dalvik class view as well

### "Split variable" for Register Variables

"Split variable" and "Unsplit variable" now work on register variables too, not only on stack variables.

The post-split occurrences are renamed to a fresh register before the use-def chains are built, so a separate variable starts at the split point. The split is validated first: the split point has to fully redefine the register, every renamed use has to be dominated by it, and a loop-carried self-referential accumulator is rejected. A function with no register split is unaffected.

### New "Create scattered pair" Operation

On 32-bit targets a 64-bit value can sit in a pair that no single storage location describes: reversed (low half in `r2`, high half in `r1`), non-adjacent (`r3`+`r12`), or a register plus a stack slot. Those used to be two 32-bit variables joined by `__PAIR64__` helpers, and retyping half of one to a 64-bit type simply failed. Pairs with evidence are now converted into one scattered variable automatically, and "Create scattered pair" / "Delete scattered pair" cover what the automatic recognition deliberately leaves alone. Scattered operands also propagate their names, so Go string variables in register pairs get their real names instead of `vNN`.

Shifts and multiplies of such a pair are fused into single 64-bit operations instead of separate `LODWORD`/`HIDWORD` updates.

* the command works on a `__PAIR__` expression or on any variable, with the other half picked from a list. The choice is saved with the function; "Delete scattered pair" also keeps the pair from being re-created automatically. When enlarging a variable fails, the warning suggests the command
* the automatic conversion needs evidence — the pair is compared, has a stack half, or occurs several times; x86 `edx:eax` pairs and 128-bit values are left alone. If the halves were named, the variable takes their name, minus a `_hi`/`_high` suffix

### Better x87 FPU Stack Handling

On x86, FPU stack recovery no longer gives up when a callee is typed as returning `void` or an integer but actually leaves a value on the x87 stack. The stack model is retried with such calls unpinned, the callee's return type is corrected, and a note names it at the call site — instead of the whole function dropping to inline `__asm`.

A function whose x87 stack model came out infeasible used to drop to inline assembly wholesale, and both common causes were callees with a wrong prototype, not the code being analyzed:

* a callee typed as returning an integer but returning in `st0` no longer pins the stack delta, so its callers decompile instead of dropping to `__asm`
* when the strict model fails, it is retried with such calls unpinned, instead of giving up with "inconsistent fpu stack"
* a prototype that cannot account for the values left on the stack gets a red header comment with the actual and the declared FPU slot counts, instead of a silent note in the Output window

### Merged Structure Fields Come Apart

A compiler initializes or compares several adjacent structure fields with one wide operation. Both are now undone when the members tile the accessed range exactly.

* each member's value is cut out of the constant in the program's byte order. Padding, a partially covered member, a union, or a base expression with side effects leaves the store alone
* `==` joins the parts with `&&`, `!=` with `||`. GUIDs benefit most: their fields show as recognizable hex constants instead of one large decimal number. Ordering comparisons are left alone
* the split is reversible per expression: "Unsplit expression" is offered on the generated assignments

### Swift Binaries Decompile Correctly Even When Stripped

The decompiler recovers the Swift calling convention and Swift error handling even when a binary carries no prototypes:

* the swift calling convention is recovered on stripped binaries: it is recorded at analysis time and applied at decompile time without being stored as a prototype, so call-site argument recovery keeps working. Arguments spilled to the stack at swiftcall sites are recovered as well
* throwing calls and functions are recovered on stripped binaries. At a throwing call the error result is surfaced as `__swift_get_error()`, so the following `if (error)` check reads normally instead of as opaque error-register traffic; a throwing function's own result type and `__swiftthrows` attribute are reconstructed
* runtime enum parameters are typed as enums instead of `void *`, and Swift is reported as the compiler in the output header

### Improved ARM64e Handling

On arm64e, a virtual call goes through an authenticated pointer whose 16-bit discriminator identifies the method being called. IDA now uses it to resolve those calls: a `BLRAA`/`BRAA` gets cross-references to the methods it can reach, and each method gets cross-references from its callers, across KEXTs too. No type information is needed.

![An authenticated virtual call in a kernelcache](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-4f9e9bf703b9a9cb82111fd39574e60da0a2ae89%2Fpac_vcall_disasm.png?alt=media)

![Jump > Cross references from: the candidate methods of that call](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-af3089a14280c6296d25191d164fb1667971bca5%2Fpac_vcall_xrefs.png?alt=media)

* a call lists every override of the method, since they all share its discriminator
* it works in kernelcaches and dyld shared caches, vtables that no symbol names included. On a kernelcache with all its KEXTs mapped, 92% of the authenticated calls name their callee
* calls through Swift's value witness tables resolve the same way

Furthermore, the decompiler now hides the tedious checking of PAC'd frame pointers on ARM64. They used to manifest themselves as `brk` instructions guarded by an if:

```
if ( ((v4 ^ (2 * v4)) & 0x4000000000000000LL) != 0 )
  __break(0xC471u);
```

The decompiler now hides them by default. If you need them back, flip the `HO_SHOW_PAC_INSNS` bit in `hexrays.cfg`.

### Minor Improvements

* GCC/Clang builtin names (`__builtin_bswap32`, `__sync_fetch_and_add`, ...) are used for non-MSVC targets
* 64-bit variables stored in scattered register/stack pairs are recognized
* a bare constant stored into an unsigned variable is shown unsigned: a byte store of `0x9F` no longer prints as `-97`, and an HRESULT reads as `0x80070057` instead of `-2147024809`
* the carry flag of a constant left shift is folded into a bitmask test
* `x ^ ~x` is simplified to `-1` and `x & ~x` to `0`
* on 32-bit targets, 64-bit shifts and multiplies held in unaligned register pairs (such as `r1:r2` on ARM) are recovered as single 64-bit operations
* a carry flag used as a boolean value — a `bool` return value, for instance — is shown as a bitmask test such as `(x & 0x100) == 0` instead of `__CFSHR__`, and the carry of a left shift often simplifies further into a sign comparison
* hints for `sizeof()` and `offsetof()` show the numeric value
* a rotation that cannot move a set bit to the other end is shown as a shift instead of `__ROL__`/`__ROR__`: `__ROL4__((unsigned __int8)fe->PrologLen, 2)` becomes `4 * fe->PrologLen`
* a call returned directly by the function takes the function's return type, so a 16-byte result such as a Rust `&str` or a Swift `String` is no longer cut in half
* the function prototype editor ('y') no longer offers the argument names the decompiler invented (`a1`, `a2`, ...), so accepting the dialog does not turn them into real names
* arc: the arguments of MetaWare variadic functions are recovered
* arc: the vararg frame of MetaWare ARCtangent-A4 code built without helpers is recognized
* arc: the MetaWare compiler's millicode helpers are handled better
* v850: the 64-bit integer helpers of the GHS and CC-RH runtimes are decompiled instead of being left as calls
* ppc: cache, barrier, load-and-reserve/store-conditional, MSR/SPR/time base and FPSCR instructions are shown as intrinsics instead of `__asm` blocks
* more `memcpy` calls, also through pointers, are turned into plain copies, so more values propagate and dead code is removed
* x64: empty C++ records are dropped per the modern System V psABI; the legacy GCC < 8 layout is the new `-sysv_pre12` ABI option, set automatically from the DWARF producer
* new option to vertically align consecutive assignments
* PPC: the thread pointer r13 is shown as **R13** instead of an uninitialized variable
* new "Mark as outlined code" toggle in the pseudocode context menu sets `FUNC_OUTLINE` on the function and refreshes its callers
* rust: return types of functions without a prototype are guessed more precisely
* batch decompilation saves each function to the database at once instead of keeping it in memory (`-noserialize` to disable)

### Bugfixes

* vd: golang: assembly functions such as `runtime.memequal` decompiled as `void`, which could delete comparisons in their callers
* vd: golang: write barriers (`runtime.gcWriteBarrier1..8`) took invented arguments, so every call site passed garbage
* vd: golang: a function with a stack argument failed to decompile
* vd: swift: renaming a function parameter changed the wrong one, and a function returning a value wider than one register caused an internal error
* vd: swift: fixed INTERR 51723 on Windows ARM64 Swift binaries
* vd: swift: Swift code in ELF/PE files was decompiled as C on first load
* vd: swift: calls whose prototype could not be used lost the Swift convention
* vd: rust: a sub-word integer argument on the stack that the compiler loaded as a full slot was shown as `*(_QWORD *)(&arg - 1)`
* vd: x86: `bt reg, reg` kept a dependency on the upper bits of the index register, producing `LOBYTE()` and "possibly undefined" variables
* vd: x86: `movq` between vector registers copied the full 128 bits instead of the low 64
* vd: x64: stack variables were not recognized in functions that align their frame pointer (AVX code)
* vd: x64: `lock or [rsp], 0` memory barriers in MSVC code produced bogus stack arrays or `_InterlockedOr` calls
* vd: arm64: values stored by prolog instructions (`STR Rt, [SP,#-N]!` in Rust code, for example) were lost
* vd: arm64\_32: decompiling code that takes the address of a stack variable could fail with an internal error
* vd: ppc: an argument following a float argument got a wrong location
* vd: ppc: restoring the TOC in PS3 ILP32 code could fail with INTERR 50836
* vd: ppc: AltiVec and byte-reversed loads in PS3 ILP32 code could fail with INTERR 50826/50920
* vd: ppc: string literals loaded through the TOC were not shown in the decompiler output
* vd: mips: in MIPS16 functions with a frame pointer, stack accesses through `$s1` were shown as reads of an uninitialized register
* vd: mips n64: references through the GOT were shown as meaningless address arithmetic, and calls through GOT slots were not resolved
* vd: v850: structure, union and bitfield accesses could fail with INTERR 51111, 51625 and 50698
* vd: decompilation could fail with INTERR 52870
* vd: x87 instructions could be left as `__asm` statements when a function called from x87 code had a wrong integer return type
* vd: a bitfield access through a struct with an incomplete member could fail with INTERR 50689
* vd: variadic arguments were invented for `printf`-like wrappers called with a literal format string
* vd: setting a local variable or argument type could crash (INTERR 1098)
* vd: a stack argument could inherit the type of a local variable that reuses its slot
* vd: clicking a demangled name did not highlight the whole name
* vd: decompilation could fail with INTERR 52482
* vd: early propagation of stack references ran before the control flow graph was built
* vd: a wrong member was used to access a small struct argument
* vd: a small struct or array passed in a wider register was accessed wrongly
* vd: a stack variable that used a guessed type could cause a crash
* vd: a wrongly defined `__m128` in the database could cause an internal error
* vd: float constants were printed imprecisely and without the `f` suffix, and were byte-swapped in big-endian databases
* vd: a 256-bit AVX store to the stack failed to decompile
* vd: `-nosave` did not prevent saving the input database
* vd: auto-renaming offered register names such as `r3_0` as variable names, and could fail with INTERR 51365 on PowerPC
* vd: "Enable SSE intrinsics" and "Hide casts" could not be undone
* vd: a guessed `__fastcall`-like calling convention could put the arguments of a call in the wrong places
* vd: setting a variable's type with "Setting type renames target" dropped or overwrote the name it already had
* vd: reading the label of an empty nested block could crash
* vd: the pseudocode restored from the database was garbled for functions with try/catch (function roles were not serialized)
* vd: renaming a structure field accessed through a typedef had no effect
* vd: opaque Windows types such as `HWND` were not replaced by their typedefs
* vd: a jump table of instructions was missed when its index was loaded from memory
* vd: pressing 'y' on the prototype line of the pseudocode did nothing
* vd: verbatim type names (Go's `[]string`, for example) were rejected by the "Set type" dialogs, and highlighted only partially in the pseudocode
* vd: changing a variable's type with automatic renaming enabled could crash
* vd: large functions could hang the decompiler (unbounded `get_bitwidth` recursion), and decompiling a switch with a huge value interval could run out of memory
* vd: many other internal errors reported by users were fixed, across x86/x64, ARM, ARM64, PowerPC, MIPS and V850 code
* vd: x64 conversions between 64-bit integers and floating point values were truncated to 32 bits
* vd: floating point NaN checks were removed from the output
* vd: magic-number signed divisions were not recognized when other code was interleaved with the division sequence
* vd: unreachable statements could be printed after a try statement or a jump
* vd: INTERR 53087 on a 32-byte AVX copy into a stack variable
* vd: a huge function with C++ exception handling crashed IDA and could not be cancelled
* vd: INTERR 52369 on a Go function returning a value in a non-standard register
* vd: INTERR 50689 on isnan() of a long double on ARM64
* vd: INTERR 50743 on a noreturn call returning a struct in several registers
* vd: cancelling a decompilation did not stop the text search in the Classes view
* vd: `continue` in a do-while loop could skip the loop condition
* vd: float operands widened to double printed as float arithmetic
* vd: a narrowing cast on a ternary branch could be dropped, changing the value
* vd: an internal error while refreshing the global xref list caused an unhandled C++ exception
* vd: "keep non-library functions" truncated the functions it kept
* vd: INTERR 50708 when a call result was used as an lvalue
* vd: memory accesses could be moved across memory barrier instructions
* vd: pointers stored through void\* were assigned to `_DWORD`/`_QWORD` lvalues, which did not compile
* vd: float input arguments could be dropped from calls to functions without a known type
* vd: gcc variadic functions that fetch no floating point varargs got spurious double arguments
* vd: decompiling some ARM64 functions that call outlined code crashed IDA
* vd: Enter on a block number in the microcode view did not jump to the block
* vd: xrefs to a structure member jumped to the "." or "->" instead of the member name
* vd: "split expression" had no effect on cdq and other sign/zero extensions
* vd: V850 data accessed via a fixed GP/TP/EP was not resolved to global variables after a call
* vd: could hang on a switch whose jump table is followed by another table
* vd: could hang on a bit test of a just-redefined register
* vd: decompiling an import thunk removed the arguments from its calls
* vd: could hang on a function ending in an endless loop
* vd: `-Ohexrays`: `-tmpfile` was ignored by batch decompilation started from the UI
* vd: an internal error in the pseudocode view closed IDA instead of being reported

## Disassembler <a href="#disassembler" id="disassembler"></a>

### Register Values Tracked Across Loops and Stack Variables

Firmware and C runtimes call arrays of function pointers in a loop — `__libc_init_array`, `.init_array`, `__libc_freeres`, driver tables:

```
s0 = address of an array of function pointers
loop:
  v0 = *s0        ; IDA wants to know where this call goes
  call v0
  s0 = s0 + 4
  goto loop
```

Those indirect calls had no cross-references, so whole subsystems stayed invisible. IDA now tracks a register that a loop changes by a constant step, and every function in the array gets a call xref; in a MIPS gzip uImage this uncovered 18 new functions.

* ARM and MIPS: a static array walked in a loop gets data and string xrefs to its elements; on ARM a structure array shows member offsets (`[Rn,#Struct.field]`), and `[Rn,Rm]` accesses and `ADD Rx, Rbase, #imm` on named data become offset expressions
* an array entry is accepted only if it points at code; the array ends at the first entry without a value, with a name or xref of its own, or that does not look like a function
* `REGTRACK_ALLOW_NUMLOOP` in `ida.cfg` switches it on per processor
* "Find a value" (Alt+Shift+V, formerly "Find register value") also resolves the stack variable under the cursor, and the return address pushed by `call $+5`
* SDK: a new loop value kind; plugins built against 9.3 see it as the old unknown-loop value

### ARC: Jump Table, Millicode Recognition and Other Fixes

* `bi`/`bih` jump tables are recovered as switches, and the ARCtangent-A4 indirect call idiom is recognized as a call
* the out-of-line millicode helpers of the MetaWare compiler are handled, and the arguments of MetaWare variadic functions are recovered
* `enter_s`/`leave_s`, the `bi`/`bih` switch jumps, multiplies, set-conditionals, divisions, `bmskn` and `min`/`max` are decompiled instead of being left as `__asm`. Functions that used to end in an asm statement and a `JUMPOUT` get real returns, and a `bi`/`bih` dispatch becomes a switch instead of always reaching case 0

Whole instruction families were never lifted, so they printed as `__asm`, and every use of their result read a pseudo-register. Every `leave_s` was a missing return.

With the products computed, the magic-multiply recognition runs and the divisions hiding behind those sequences come back. The flag-setting `.f` forms follow the "STATUS32 Flags Affected" table of the ARCv2 PRM:

```c
// 9.4
_R3 = g_timer_int_count;
__asm { mpyhu r3, 0xAAAAAAAB, r3 }
if ( _R3 >> 2 < dword_100007A0 )
__asm { mpy r0, r0, sizeof(gpio_info_t) }
v6 = (gpio_info_t *)((char *)gpio_ports_devs + _R0);
// 9.5
if ( g_timer_int_count / 6u < dword_100007A0 )
v6 = &gpio_ports_devs[dev_id];
```

Some instruction sequences used to decompile to wrong code: `bbit0 r13, r15, loc` used `r15` — its own second operand — as scratch and then zeroed it, so everything after the branch read 0 instead of the loop counter. The same defect was in `asr`/`lsr`/`asl`/`ror` and `btst`/`bset`/`bclr`/`bxor`/`bmsk`. The GCC millicode prolog/epilog helpers and the vararg home area are handled as well as the MetaWare ones.

### ARM: More Armv9 Extensions

The disassembler decodes FEAT\_LUT, FEAT\_CMPBR, FEAT\_CPA, FEAT\_LSUI, FEAT\_FPRCVT, FEAT\_MOPS, FEAT\_FCMA and FEAT\_SPECRES2. These are becoming mandatory in recent versions of the architecture.

FEAT\_PAuth\_LR (Armv9.5), already used by Apple's latest kernels, is supported as well: functions that sign their return address with `PACIBSPPC` and return with `RETABSPPC` are created, their ends are found, and the return is linked back to the function:

```
_bzero
        PACIBSPPC
        STP             X29, X30, [SP,#-0x10+var_s0]!
        ...
        LDP             X29, X30, [SP+var_s0],#0x10
        RETABSPPC       _bzero
```

### Hexagon: No-Return Analysis, Absolute Memory Target Handling, Switch-Case Discovery, Function Epilogues

Lots of improvements and bug fixes. Here are some highlights:

* GP-relative (small data) accesses are resolved against `_SDA_BASE_`, set with the new `QDSP6_SDA_BASE` keyword or in the processor options
* the ELF loader computes GOT and GOTREL relocations as the ABI specifies, handles the TLS relocations, and applies `R_HEX_32` to DWARF
* the epilog is found by the frame slot an instruction restores, not by its position, so predicated early returns are covered

```
// 9.4                                   // 9.5
r1:0 = memd(gp + #0xC8)                  r1:0 = memd(gp + #(.CONST_4040800000000000 - _SDA_BASE_))
r0 = memw(r17 + #-0x1A78)                r0 = memw(r17 + ##(listener_mut_ptr - _GLOBAL_OFFSET_TABLE_))
r0 = add(pc, ##loc_14@pcrel)             r0 = add(pc, ##.L.str@pcrel) // "Hello, World!\n"
memw(##0x4024C)                          memw(##g_a)
```

### Support for MIPS R6 Instructions

IDA now fully supports MIPS Release 6 in both the disassembler and the decompiler:

* all R6 integer and FPU instructions are decoded, including those introduced with new encodings in R6
* compact branches and jumps are supported
* the decompiler handles R6 branches, jumps, selects and FP comparisons
* R6 can be selected for plain (headerless) binaries, and PLT stubs are named

![MIPS R6 code in the disassembly and the pseudocode](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-3d4b95a04ef65d75b8507c28e433cb57b90c7802%2Fmips-decompiler.webp?alt=media)

### Renesas RX: Big-Endian Code

The new "rxb" processor type handles RX firmware running in big-endian mode. In that mode the CPU fetches code as 32-bit words, so flash dumps and linked executables store each aligned word of code with its bytes reversed, while data stays big-endian.

* big-endian ELF files select "rxb" automatically; for binary, Intel HEX and S-record images choose "Renesas RX big-endian" when loading
* the byte-swapped code layout is assumed for big-endian memory images and can be turned off in the processor options ("Code is stored as byte-swapped words"), e.g. for objcopy output that keeps code in instruction order
* relocatable ELF objects and `--emit-relocs` executables from CC-RX and GCC are supported
* on both RX types, `rts`/`rtsd`/`rte`/`rtfi` are recognized as returns, so more functions and their ends are found

### Game Consoles: PlayStation 3, Xbox 360, Wii U and PlayStation Portable

PS3, Xbox 360 and Wii U are PowerPC; the PSP is MIPS.

* PlayStation 3: the disassembler and decompiler support 64-bit PowerPC with 32-bit pointers (celloslv2 ILP32). PS3 executables load with ILP32 segments and correct TLS variable addresses.
* Xbox 360 and Green Hills (Wii U): the out-of-line register save/restore helpers (`__savegprlr_N`/`__restgprlr_N`, `__savefpr_N`/`__restfpr_N`, `__savevmx_N`/`__restvmx_N`) are now named. The decompiler treats them, and their PS3 counterparts, as prolog/epilog. Callers decompile with correct arguments and return values, and without spurious calls. You no longer need to type the helpers as `void __spoils<>()` by hand.
* Xbox 360: stubs that use `r12` as the link register or save vector registers are handled too. For example, the tail of a function that jumps into a restore helper:

  ```c
  // 9.4
  sub_80062000(v4);
  JUMPOUT(0x80078B0C);
  // 9.5
  sub_80062000(v4);
  return v6;
  ```
* Xbox 360: `.pdata` entries are decoded with their own layout, not as a Windows CE variant. Hand-written stubs with the 32-bit flag clear no longer have their length halved.
* PlayStation Portable (Allegrex): a new `single_float` ABI option, on by default, passes floats in consecutive FP registers and doubles in GPRs. The decompiler uses the same ABI to reconstruct prototypes, so float and double arguments are deduced correctly.
* PlayStation Portable: the ELF loader supports packed PRX relocations.
* AltiVec/VMX128 Intrinsics: on PPC, AltiVec/VMX128 vector instructions are shown as intrinsics named after the Xbox 360 XDK ones (`__lvx()`, `__vaddfp()`, ...), with real vector variables as arguments and results:

  ```c
  do
  {
    v4 = __vmaddfp(*result++, *a2++, v4);
    --a3;
  }
  while ( a3 != 0 );
  ```

### WebAssembly 3.0, and Large Modules That Load in Minutes

The WebAssembly loader and processor module now support WebAssembly 3.0. Modules that use garbage collection, typed references, exceptions or SIMD, such as those built by Kotlin/Wasm, were rejected by IDA 9.4 and now load. Large modules from Emscripten, Rust and other toolchains load several times faster.

![A Kotlin/Wasm module in IDA 9.5](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-1fd17e423b1b2a2fed32f0e6579e96c3ec875466%2Fwasm_after_95.png?alt=media)

* the WebAssembly 3.0 instruction set: garbage collection, typed references, exceptions, SIMD, atomics, tail calls, 64-bit and multiple memories
* a readable disassembly: stack code is folded into operands, blocks are indented and the one around the cursor is highlighted, and names come from the module
* signatures become function prototypes, and GC structs and arrays become local types

Measured on 32 real-world modules (Emscripten, Rust, Go, Qt, onnxruntime, pyodide, ...):

| module                           | before                   | after      |
| -------------------------------- | ------------------------ | ---------- |
| 62 MB Qt/Emscripten module       | did not finish in 45 min | 102 s      |
| 27.8 MB module, 68,069 functions | 39 min 40 s              | 1 min 17 s |
| 22 MB Emscripten module          | 379 s                    | 40 s       |
| pyodide                          | 121 s                    | 15 s       |

The listing is also cleaner: far fewer false offsets in data, linear memory no longer listed byte by byte, and malformed modules no longer crash or hang IDA.

### Bugfixes

* x86: jmp using pointers to SEG\_XTRN segments had no code xref
* arm: added the system registers and operations of the Arm A-profile 2026-09 specification
* arm: added support for FEAT\_S1POE2 and FEAT\_TEV
* arm: a function could be split in two at PACIBSPPC (FEAT\_PAuth\_LR)
* arm: a virtual call whose possible targets include a non-returning function ended its function early
* arm: arm64e virtual calls listed the pure-virtual trap as a callee
* arm: arm64e virtual calls into a KEXT loaded later got no xrefs once it was loaded
* arm: arm64e virtual calls through the first slot of a vtable got no xrefs
* mips: psp allegrex: malformed VFPU instructions could crash IDA while decoding
* mips: a loaded word that held the address of MIPS16 or microMIPS code (ISA bit set) stayed a plain number instead of becoming an offset
* mips: PLT entries and lazy binding stubs in n64 binaries, R6 binaries and binaries built by newer binutils are now recognized as thunks
* mips: the unaligned stores `usw` and `usd` were treated as loads, so code using them was rolled back to data and their cross-references were marked as reads instead of writes
* mips: unaligned stores (usw/usd) were treated as loads
* mips: IDA crashed analyzing a function whose entry is the delay slot of a branch in its own tail chunk
* ppc: in binaries with several TOCs, the TOC value was not resolved for functions without an `.opd` entry
* ppc: corrected the operand flags of many instructions
* ppc: Xbox 360 binaries are now decompiled as ilp32 code
* ppc: 128-bit integer return values and stack arguments had wrong locations
* dalvik: removed the DEX Type Names view, now Local Types is the single source of truth
* dalvik: casts on an accessed object were printed without the parentheses Java requires
* dalvik: accesses to inherited instance fields were shown as **iget**/**iput** helpers
* dalvik: the first stack walk of the debugger was slow on large apps
* dalvik: debugger showed "?" or "Bad type" for arguments in code without debug info
* dalvik: debugger showed "No error" instead of the value of object locals
* dalvik: attaching the debugger to a large app took minutes
* dalvik: debugger lost all call stacks after showing a thread without Java frames
* dalvik: debugger showed "JDWP error: NATIVE\_METHOD" for stacks with a native method
* dalvik: the ANDROID\_SDK\_ROOT environment variable was ignored when looking for adb
* dalvik: JDWP\_WAIT\_FOREVER could still time out and break the connection
* dalvik: source breakpoints could fail in methods of a class renamed in Type Names
* hexagon: read the small data area base from the startup code while loading
* hexagon: learn the small data area base from "gp = Rs"
* hexagon: recognize a jump table indexed by a bit field
* hexagon: recognize a jump table whose range check also sets the out-of-range result
* hexagon: a string literal lost its first character
* hexagon: dmwait lost the register it writes
* hexagon: an unmodelled instruction could delete what it reads
* hexagon: a store of a register the function had overwritten was taken for a prolog spill
* hexagon: recognize a jump table whose default case falls into the dispatch
* hexagon: recognize a jump table whose dispatch is folded into one packet
* hexagon: recognize the restore helpers that are jumped to, not called
* rx: a jump or call could get a wrong target when a fixup followed it
* rx: a jump or call could get a wrong target when a fixup followed it
* spu: binary files were disassembled as little-endian
* v850: IDA View could hang, reloading forever, on a GHS 'callt \_\_\_ghsld4\*' function return
* sh: IDA detects functions that do not return

## Analysis & Kernel <a href="#analysis" id="analysis"></a>

### Exception Handling: Correct Stack Levels and Robust Try Blocks

A landing pad is entered by the unwinder, not by the code in front of it — yet IDA took its stack pointer level from the preceding instruction, and every stack variable after it was off.

* a landing pad now takes the stack level of the region it guards. The fix is in the kernel, so it covers every processor module that lets the kernel compute block levels: ARM, MIPS, PPC, RISC-V, SH4, Hexagon, NDS32 and TriCore
* x86: the landing pads of gcc-built PE files (MinGW, Cygwin) get the levels of their guarded region, as ELF files already did; the handler and filter funclets of a Windows `__try` are no longer fed to the SP model, since the OS calls them with frames of their own; and the stack cleanup after a call to a non-returning function, or in a handler of a region that does not end the block, gets the right delta
* one malformed try block no longer discards all the others in the same range (a function with 7 good blocks and 1 bad one returned none), and a block reaching past the end of the program no longer hides the later ones
* the guarded region of a C++ `try` block is part of the function even when it ends with a call that never returns, and the landing pad of an empty exception specification is no longer lost
* x64 epilogs restoring registers from `[rsp]` without a displacement are recognized
* files with a huge exception handling table analyze much faster, and files without SEH handlers skip the search for their owners

### Minor Improvements

* analysis: the new `OVERSIZED_FUNC_SIZE` option in `ida.cfg` (default 0, off) flags larger functions as oversized (`func_t::is_oversized()`) and records a problem; on x86/x64 their stack-frame, SP, switch-table and stack-variable analysis is skipped. This protects against binaries built with huge functions to slow IDA down
* analysis: the new `JUMPTABLE_MAX_INSNS` option in `ida.cfg` bounds the work of a single switch pattern match, so obfuscated code cannot make one switch stall the analysis
* the final analysis pass no longer hides strings in arrays (Vladimir Vishniakov)
* Strings: the listing shows a synthetic string where the code uses it (Julian Kirsch)

### Bugfixes

* analysis: struct-typed stack variables named `~rN` were shown as `byte`
* types: a structure whose first member is empty, passed in registers as gcc does, could cause INTERR 10147
* analysis: a prototype guessed from a demangled name could discard a good one
* analysis: 128-bit values were shifted right incorrectly by 64 bits or more
* arm64: Windows computed 128-bit products and quotients incorrectly
* types: a gcc enum whose values need 64 bits got a 16-byte type
* analysis: "autoanalysis finished" was not the last message
* analysis: a type guessed from the symbol name was preferred over a type library prototype
* analysis: the initial autoanalysis could take hours on a file with a huge array
* database: closing a database could end with internal error 840
* names: a function reached through a named thunk was given a suffixed duplicate of the thunk's name
* names: names starting with a dummy name prefix could crash IDA
* sdk: `DBFL_COMP` was ignored by `save_database()`
* names: forced renames could corrupt names supplied in the database encoding
* sdk: `fpvalue_t::to_float`/`to_double` returned byte-swapped values on big-endian databases
* with the xref cache off, xref walks in a rebased database skipped or repeated xrefs

## Loaders <a href="#loaders" id="loaders"></a>

### New UEFI Loader and Plugin

IDA 9.5 ships with a new UEFI plugin and loader. We still plan to refine this plugin in next beta versions and releases. The main focus was on the DXE environment for this release.

An entire UEFI firmware image (SPI flash dump, capsule body or firmware volume) can be loaded into one database. The new UEFI plugin analyzes UEFI modules, both single EFI/TE files and every module of a firmware image. It runs automatically after auto-analysis and adds names and types, allowing known protocols calls to decompile to readable code:

```
gBS->LocateProtocol(&gEfiPcdProtocolGuid, NULL, (void **)&gEfiPcdProtocol);
gEfiPcdProtocol->GetBool(1068);
```

* Entry points are named after their module and typed by FFS file type. In a firmware image, functions are grouped into folders by module.
* Globals pointing to service tables: `gBS`, `gRT`, `gST`, `gSmst` and `gImageHandle` are automatically found and typed.
* Protocols: installs, locates and notifications are found. GUIDs, interface pointers and implementations are typed and named, e.g. `DiskIoDxe_EfiDriverBindingProtocol_Start`. Currently vendor protocols that no type library describes get a synthesized structure, but this behavior might still change.
* A new "UEFI protocols" window (View > Open subviews) lists every install, uninstall, locate and notify, with filters by kind and by module type (accessible via right click).
* Cross-references are added from protocol member calls to their implementations, across modules. Double-clicking `x->Member` in the pseudocode jumps to the implementation, and a popup action lists a member's call sites. This works when a structure for the protocol is available.
* Read-only strings in `.data` are shown inline, and `DebugPrint`/`DebugAssert` calls are recognized.
* Options are in `cfg/uefi.cfg`.

### Minor Improvements

* loader: zstd-compressed input files are decompressed transparently
* loader: Intel HEX files with 255-byte data records failed to load
* dex: DEX items are shown decoded instead of as stored comments
* dex: DEX version 040 files are supported
* dex: all try blocks are kept for methods with more than 127 of them
* dex: VDEX files are supported
* elf: arc: `R_ARC_H30` relocations are supported
* macho: the kernelcache and dyld cache headers are shown expanded
* macho: load commands are typed from the type libraries, and path fields link to their strings
* macho: the `vmaddr` of `LC_FILESET_ENTRY` is shown as an offset to the KEXT's header
* macho: `arm64e.x1` files are recognized and labeled
* macho: the Functions list has a folder per KEXT or cache image
* macho: listings show a signed binary's entitlements and hardened runtime
* macho: patched bytes listed the last byte of relocated 64-bit pointers
* macho: apply patches to input file corrupted Mach-O files with chained fixups
* pe: the POGO debug information is shown as records with section names
* pe: the POGO debug records refer to the starts of their section groups
* elf: rx: support ELF relocations of the form symbol+offset pointed to symbol+2\*offset
* elf: rx: an 8- or 16-bit branch relocation in an ELF object created code in the middle of the branch instruction
* elf: rx: add big-endian support (processor type "rxb")

### Bugfixes

* elf: mips: `R_MIPS_PC32` relocations were not applied
* elf: mips: calls to external functions were not resolved in MIPS n64 object files
* elf: mips: when several HI16 relocations were paired with a single LO16 (a GNU extension), only the last HI16 of the series was applied
* elf: mips: PSP relocations exposed both as sections and as a program header were applied twice
* elf: mips: in MIPS16 and microMIPS binaries, some entries were named one byte into the stub, so no function was created for them and calls showed `jal byte_XXXX` instead of the import's name
* elf: mips: in unstripped MIPS16 binaries, the literal pools after each function (`__pool_*` symbols) were disassembled as instructions
* elf: rx: an 8- or 16-bit branch relocation in an ELF object created code in the middle of the branch instruction
* elf: rx: relocations of the form symbol+offset pointed to symbol+2\*offset
* dex: malformed uleb128/annotation offsets could cause INTERR 2765 during loading
* dex: a malformed DEX file could crash IDA while loading
* hex: Intel HEX files with 255-byte data records failed to load
* macho: a corrupted bind opcode created a bogus import
* macho: cross-references for tagged pointers in files with chained fixups were wrong
* macho: DriverKit RPC selectors are named after their SDK class and method, in drivers and kernelcaches
* macho: DriverKit RPC methods are recognised from their code and symbols, in drivers and kernelcaches
* mbn: hexagon: a bogus second "start" entry 0x10 bytes below the entry point
* mbn: hexagon: take the small data area base from the symbols or .sdata
* elf: hexagon: take the small data area base from .sdata without *SDA\_BASE*
* dscu: a move of some segments only was taken for a rebase of the cache
* dscu: when the indirect symbol table was stripped, `__auth_stub` entries were not named after their own callees
* dscu: swift: functions were no longer grouped by module in a shared cache
* kcu: in a reopened database, KEXTs loaded on demand got no C++ classes, nor xrefs from the virtual calls waiting for them
* kcu: after a rebase, KEXTs loaded on demand went to their old addresses
* kcu: plugins did not see the KEXTs loaded on demand
* kcu: faster load of many KEXTs, stable wait box, cancellable C++ reconstruction

## Type System <a href="#typesystem" id="typesystem"></a>

### Clang Is the New Default Parser

IDA 9.5 parses type declarations with a built-in clang-based parser: C, C++, Objective-C and Objective-C++ declarations work out of the box, with no setup required. The legacy parser remains available in the "Compiler options" dialog. The default is `TYPE_PARSER = "clang"` in `ida.cfg`; `"legacy"` still works. The type editor and Local Types have a language selector (C, C++, Objective-C, Objective-C++), saved per database.

**Removed:** The `old_clang` parser, the idaclang plugin and the standalone `idaclang` tool, deprecated in 9.4, are removed. `tilib -TC` is the tool for building type libraries; the documentation has an idaclang → tilib command map.

### Version-Matched XNU Type Libraries for Apple Silicon macOS Kernels

When loading an Apple Silicon macOS kernel, IDA now automatically applies the XNU type library that matches the kernel's OS version, so kernel structures and function prototypes are typed correctly out of the box.

### Tuples Named After Their Members

Functions that return several values at once (Go functions with multiple results, values the decompiler finds returned in several registers, Rust functions returning arrays) used to get a made-up type per function: `retval_401000`, `retval_401080`, and so on. These types are now named after what they contain, and functions returning the same kinds of values share one type: every function returning two 64-bit values uses `_2__QWORDs`, and a Go function returning `(bool, error)` uses `_bool_error`.

* Local Types no longer fill up with many identical per-function types, and the name tells what a type holds without opening it
* the name lists the member types separated by `_`; adjacent members of the same type are written once with their count: `{ _DWORD; _DWORD; double; }` is `_2__DWORDs_double`. Pointers get `_ptr` (`char *` is `char_ptr`), and a wrapper around an array is named after the elements and the dimensions: `int_x2x3`
* ordinary structures and unions named this way get a `struct_` or `union_` prefix, so they never clash with tuples of the same members: `struct { int; char; }` is `struct__int_char`, `union { int; char; }` is `union__int_char`
* a type whose members cannot be named this way gets an anonymous name made of `$` and an MD5 hash of the type
* `retval_<address>` types in existing databases keep working
* for plugin and script authors: `tinfo_t::create_tuple()` creates such a type from a list of member types, or reuses an equal one; `save_type(NTF_AUTONAME)` saves any structure or union under a name built from its members; `udt_type_data_t::build_autoname()` only builds the name. All three are available in IDAPython

### Minor Improvements

* XNU: kernel classes whose members are XNU-private now have their real layout
* types: structures can declare the order their bitfields are allocated in
* clang: the deprecated `old_clang` parser and the standalone `idaclang` tool have been removed; use the built-in clang parser and `tilib -TC` instead
* tilib: added options: `-CT-dump-macros`
* tilib: added tilib options: `-CT-ast-dump`, `-CT-ast-print`

### Bugfixes

* clang: a bad declaration was not reported to the user
* clang: some declarations that the legacy parser accepted, such as a non-standard prototype for `main`, were rejected
* clang: headers emitted by IDA with anonymous types could not be parsed back
* clang: demangled data declarations of const objects were rejected
* clang: names known to the type library or the compiler were not resolved
* clang: types guessed from demangled MSVC names were wrong
* clang: structure packing passed in flags was ignored
* clang: prototypes without a calling convention did not keep the platform default calling convention
* clang: on targets where `int` is not 32-bit (e.g. 16-bit DOS), `__int32` and the other `__intN` types followed the width of `int`
* clang: a declaration with an unresolvable `decltype()` crashed IDA
* clang parser: a structure typedef used by value after being used through a pointer crashed IDA
* types: function arguments could not be named after registers, which also broke "Add argument" on MIPS
* types: reject `__swiftself` on non-pointer arguments

## Debug Info, Demangling and Exception Handling <a href="#debuginfo" id="debuginfo"></a>

### Minor Improvements

* demangler: swift: names produced by Swift 6 compilers are demangled
* dwarf: zero-sized Rust parameters are dropped
* dwarf: the Rust unit type `()` is represented as a zero-size struct in aggregates
* dwarf: zero-sized members are dropped from Rust structs and unions
* dwarf: `DW_AT_noreturn` on subprograms is honored
* dwarf: Objective-C/Swift runtime root classes are represented with their isa pointer
* pdb: the bitfield allocation order is recovered from the debug information
* goodname: new patterns for MSVS STL names

### Bugfixes

* demangler: cv/reference qualifiers on a substituted template-id were misplaced
* demangler: names with braced initializer lists in template arguments were not demangled
* demangler: some local C++ names were not demangled
* dwarf: `DW_AT_type` and names were not applied to globals (and function-local statics) whose location used `DW_OP_addrx`
* dwarf: function arguments spilled to SP-relative slots were not named and typed
* dwarf: incomplete C++ types were dropped to `void` instead of being recovered
* dwarf: PowerPC floating-point arguments were mapped to the wrong registers
* dwarf: the hidden environment pointer of Rust closures was not recovered
* dwarf: C++ base subobjects smaller than `sizeof(base)` were rejected
* dwarf: decompiling a GCC `-O0` function could replace its DWARF prototype, e.g. an `int` return became `__int64`
* pdb: the "Load types" option was ignored (type processing was not skipped when it was off)
* pdb: function prototypes were not applied for COFF objects with embedded `/Z7` debug info
* pdb: some MSVC COFF objects compiled with `/Z7` got wrong argument types
* pdb: struct and array data globals were not laid out from debug info
* pdb: functions returning a small struct had a missing or extra result pointer
* pdb: functions returning a small struct had a missing or extra result pointer

## UI & UX <a href="#uiux" id="uiux"></a>

### From Qt 6.8 LTS to Qt 6.12 LTS

Qt 6.12 is the next long-term-supported Qt.

* IDA follows the desktop's light/dark scheme (on Linux through the XDG desktop portal); `IDA_COLOR_SCHEME=light|dark|auto` forces one
* the dedicated Copy/Undo/Back/Exit keys some keyboards have are registered as shortcuts, and the shortcut editor, cheat sheet and command palette list them
* PySide6 is upgraded along with Qt: retest plugins that use PySide

### HTML Export

Every listing — disassembly, hex, pseudocode, type listing — can be copied and exported faithfully, colors included.

![The Copy submenu: as text, as HTML, or as a deeplink](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-e07aa63c1b7f97aa9ea7808319275bbd36c90438%2Fhtml_copy_as_html.png?alt=media)

The context menu's new **Copy** submenu copies the selection or the current item **as text** (Ctrl+C), **as HTML** (pastes styled into any HTML-aware editor or chat), or **as a deeplink**.

![The Export to HTML dialog](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-d589808aee1a394d0363d01aea4ea93170fb7fbc%2Fhtml_export_dialog.png?alt=media)

![An interactive export of a type listing, in a browser, with its sidebar](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-ea2812c0711bc3ce48e578e5736c588b71eee482%2Fhtml_export_interactive.png?alt=media)

**File > Produce file > Export to HTML...** exports a standalone page, an interactive page with a function sidebar and working cross-reference links, or a paste-ready snippet. Templates are plain IDAPython scripts, and the export is available to plugins, IDAPython and idalib.

**Migration:** the decompiler's own "Generate HTML" action is retired in favor of this export.

### Interactive Pathfinder

The Pathfinder answers questions such as "how does this malware get from `WinMain` to `connect()`?". In 9.5 you build the path as you go: add waypoints and exclusions from any window that shows addresses, and the path updates at once. The list on the left and the graph on the right are two views of the same path, and you can work in either.

![The Pathfinder: the path as a list on the left, as a graph on the right, with the shortest route highlighted](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-c7298750a9045b2c89c72b39342c6021a86e7f68%2Fpathfinder_with_xref_graph.png?alt=media)

![Between two waypoints: how many functions connect them, a direct connection, or no path at all](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-9110ef758f7fd8710f9857f4a55b6df3d0d46805%2Fpathfinder_segments_no_path.png?alt=media)

* between two waypoints, IDA shows how many functions connect them and how short the shortest route is, or that there is no path
* paths are saved in the database

The xref graph is also easier to read: edges are routed at right angles, and string literals show their contents.

**Migration:** "Open Pathfinder" gave its shortcut, Shift+F9, to "Create new path".

### Reworked Quick Filter Mechanism

* typing in a list window (Functions, Names, Imports, Local Types, ...) now filters it, instead of running the old incremental search, which was hard to discover. Shortcuts always take precedence over typing
* the filter bar is always visible, so it is clear where what you type goes

**Deprecation:** the old behavior is available under **Options > Feature Flags** during 9.5, and goes away in 9.6.

### Jump Anywhere Shows More and Finds More

Jump Anywhere finds everything from one box: functions, names, strings, local types, their members and enum constants. Results are syntax-colored, functions show their parameters, and each result is previewed as you move through the list.

![One query, every kind of result: types, functions with their parameters, strings](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-67b7a3d48b014771a411bcc362fb31d0e549d0f8%2Fjumpanywhere_mixed_results.png?alt=media)

![A type and its members, the type previewed as a type listing](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-bdf15b29d3e65b7d436bb4e1d9a5df7e04120720%2Fjumpanywhere_type.png?alt=media)

* local types, their members and enum constants are found by name, raw or prettified, and preview as a type listing
* the preview shows the disassembly, the pseudocode or the hex view, and is always on
* expressions can be evaluated in IDC or in Python
* while debugging, it also finds the symbols of the modules that the debugger loaded

### Minor Improvements

* the widget numbers for Alt+ window switching appear after 500 ms instead of 1 s
* demangled names are displayed by default
* "deep select" for grouped names: Alt-click a qualified name to highlight only the component under the cursor
* qualified names are highlighted as a whole
* double-click jumps to a type's definition (in prototypes) or to a struct member (in operands)
* pressing in a chooser embedded in a form no longer closes the enclosing dialog
* Shift+Enter in choosers and tree views jumps to the item without moving the keyboard focus
* the type editor reads a declaration as C, C++, Objective-C or Objective-C++
* the type editor has a new "Declaration" tab, and the Compiler options dialog is more compact
* Ctrl+drag selects whole lines
* the raw name behind a prettified one is painted translucent
* hovering a prettified type name shows its full name
* the Types window shows and filters on the prettified type name
* dsc: kc: the DSC Index and KC Index trees are sorted alphabetically
* teams: the status bar panel names the workspace and details it in its tooltip
* teams: its status is reported in a single status bar panel
* "Export data" moved from the Edit menu to **File > Produce file**
* a new "Extensions" menu gathers Lumina, Teams and the other Hex-Rays extensions; the Lumina and Teams top-level menus are gone, but plugins attaching actions to "Lumina/..." or "Teams/..." menu paths keep working
* a newly loaded file opens on the monitor where the main window is, instead of always on the primary monitor
* pathfinder: paths are saved and listed in the "Pathfinding" submenu
* pathfinder: dead-end pairs are swapped automatically, and the hovered segment is highlighted
* pathfinder: new "Promote to waypoint" action, and one popup menu for all three views
* pathfinder: nodes grown by hand stay in the path
* pathfinder: waypoints are shown as a tree of each segment's nodes
* pathfinder: path actions work in every window that has addresses
* pathfinder: a path segment can be folded to its shortest path
* pathfinder: "Delete selected nodes" in the waypoint tree's context menu
* xref graph: Ctrl+Up/Down jumps between connected nodes
* xref graph: the bottom bar shows node and selection counts
* xref graph: zooming has a keyboard shortcut
* xref graph: the contents of string literals are rendered in nodes
* xref graph: edges are routed orthogonally in the layout
* xref graph: the edges of a dragged node stay orthogonal
* xref graph: nodes and edge bends have rounded corners
* choosers and tree views got a "Copy" submenu: copy the selected rows, copy the current cell, copy as deeplink
* a plugin can group itself in a submenu of Edit>Plugins with a slash in its name; the SDK samples are grouped under "Examples"
* names that could merge with the code around them are shown in backticks
* git: repositories follow IDA upgrades; git-ida entries are repointed automatically

### Bugfixes

* teams: the file trees triggered INTERR 80130 after pulling a file from the vault
* teams: opening the "Vault files" widget triggered INTERR 72549
* macos: the widget numbers used for Alt+ window switching appeared while holding Cmd instead of Option
* licensing: a license server selected at runtime was forgotten after closing the database
* the "Load a new file" dialog did not highlight the chosen processor in bold
* the "Analysis" toolbar indicator did not turn green when analysis was idle
* in the Local Types view, clicking a qualified type name did not highlight the whole name
* pressing Enter did not accept a form when focus was on a checkbox or radio button
* opening the navigation drop-down of a view that shares its history with a different kind of view crashed IDA
* pressing in a tree view's quick filter did nothing
* middle-clicking a tab closed two views instead of one
* a chooser's "Line N of M" counter went blank in folders-only mode
* changing the demangled names settings did not update the windows right away
* the "bottom line padding" setting had no effect
* typing a character that needs AltGr in a list (as Polish, Croatian and Vietnamese layouts do) did nothing
* the wrong segment attribute was used to calculate the segment base
* the release notes were shown again on every start when switching between two IDA versions
* disabled check boxes and radio buttons looked enabled in the dark theme
* the Pathfinder and the Scripts window had no Alt+N number
* a mouse selection cleared the clipboard on Wayland
* tree views such as Bookmarks and Breakpoints showed "Edit function"/"Delete function" in their popup menu after the Functions window had been used
* the prototype editor's validity indicator checked stale text
* pressing in a dialog discarded the changes when a checkbox had the focus
* "Copy full type" was unavailable on function types in Local Types
* pathfinder: the selected waypoint row was unreadable in light mode
* pathfinder: a node could be a waypoint and an exclusion at once
* a backward search did not walk the occurrences in order
* an identifier search did not find the next occurrence
* a type whose member references a non-C type name could not be edited in C syntax in the type editor
* copying several rows of the xref tree did not keep the tree order
* xref graph: the headers and icons of rendered nodes overlapped each other
* xref graph: node icons activated on press instead of on click
* "Edit location" in the function prototype editor did not show the current register of an argument
* highlighting a register no longer matches it inside other words (e.g. r8 in cr8)
* the Teams file trees kept scheduling reloads of themselves while loading their own data
* the Teams file trees triggered an internal error 40795 when the current item was inside a collapsed folder
* or a double-click on a type's header in a loaded type library offered to edit the type
* in a tree view, the first keyboard move after opening left the last cell of the previous row painted as selected
* in a text field with a history, skipped the most recent entry
* the type name field of the "Add type" dialog lost its input history
* macOS VoiceOver could crash when filtering table choosers
* tree filter highlights could be unreadable in OS dark mode
* a list without a filter or status bar left blank space below its rows
* switching to an expired license with no database open crashed IDA
* loading a file with an unavailable processor module no longer crashes IDA
* the wait box shown while unpacking or packing a database did not display its message
* number fields of the new dialogs accept arithmetic expressions again

## Debuggers <a href="#debuggers" id="debuggers"></a>

### Bugfixes

* android: suspending an app running JIT code could hang and kill it
* linux/android: internal error 30057 after attaching to a busy app
* linux/android: a job-control stop froze the debugged process
* linux/android: detaching left the process stopped
* linux/android: some new threads ran undebugged and could crash the app
* linux/android: SIGCONT made the debug server abort and kill the app
* a malicious client could crash the remote debug server with a bad file index
* bochs: Try to make single stepping with page bpts a bit faster
* the debugger's Threads window shows the instruction pointer of each thread

## FLIRT & FLAIR <a href="#flirt" id="flirt"></a>

### Minor Improvements

* flirt: a pattern can be created from a selected byte range
* flair: pelf: ARC ELF files are supported
* flirt: signatures can carry original (unmangled) symbol names
* flirt: narrow/wide MSVC runtime twins (main/wmain, WinMain/wWinMain, argv accessors, environment helpers) are named from evidence in the binary
* flirt: the ARM and ARM64 MSVC runtime signatures are regenerated and cover VC11 through VC 14.52
* flirt: the 64-bit MSVC runtime signatures are picked by the CRT linkage of the binary
* flirt: the functions and data that the entry module of a startup signature references are named
* flirt: a startup signature is accepted even when its references are not resolved yet
* flirt: the names of the narrow/wide startup globals are kept
* flirt: 32-bit MSVC binaries of VC 14.39–14.52 are recognized, and their runtime is picked by the CRT linkage
* flirt: arc: a new signature covers the millicode helpers

### Bugfixes

* flirt: a 32-bit wWinMain program lost the name of its entry point
* flirt: a startup signature applied as an ordinary one named its entry module after the directive string
* flirt: a short wrapper could take the name of a library function like exit
* flirt: library functions found late in the analysis stayed unrecognized
* flair: sigmake could crash on a .pat file with a pattern longer than 65535 bytes
* flair: ppsx PSX object parser could crash on a crafted object file with an oversized section
* flair: pmacho dereferenced an out-of-bounds section on a crafted symbol
* flair: zipsig double-closed the output file on a malformed signature
* flair: pmacho could write past a section buffer on a crafted Mach-O object
* flair: pelf could write out of bounds on a crafted ELF object file
* zipsig: guard write\_node against a null or malformed tree node

## Performance & Resource Consumption <a href="#performance" id="performance"></a>

### Large Binaries: Less Memory, Fewer Stalls

* **DWARF at scale:** debug sections are memory-mapped instead of read into memory, which saves about 2 GB (−30%) on a 2.6 GB C++ binary, and the per-DIE index on an 89.5-million-DIE binary shrinks from 2048 MB to 1109 MB. The new opt-in `-Odwarf:lazy_types=1` imports only the types reachable from named functions and globals, so huge C++ binaries that used to run out of memory load
* **dyld shared caches:** enabling an address range no longer rewrites the whole database. On a 2.7 GB cache, initial load and analysis freeze the UI for 8.1 s in total instead of 42–48 s (worst single freeze 5.4 s instead of 13.5–15.9 s; UI-thread I/O 21 GB instead of 234 GB). Building the cache's region map takes 1 s instead of 5 s
* **pathological inputs:** the data copied by RTTI analysis of a file with 800 classes and 200k strings drops from 37.1 GB to 36 MB; auto-analysis of huge functions with flattened control flow (a dispatcher on a state register) drops from 1751 s to 253 s; creating names in a reopened database no longer slows down as the database fills; binaries built to slow IDA down can be reined in with `OVERSIZED_FUNC_SIZE` and `JUMPTABLE_MAX_INSNS` (see Analysis & Kernel)
* **decompiler:** batch decompilation no longer slows down quadratically (8% faster on 26k functions, 11.8% on 74k); decompiling a function with one 5506-instruction basic block drops from 2929 s to 148 s
* **FLIRT:** signature files are read through a buffer instead of a byte at a time
* **start-up:** parallel IDA instances no longer keep rebuilding the processor module cache, and a run without IDAPython no longer forces the next run to reload every processor module (running the shipped Python processor modules costs about 200M instructions)
* **databases:** "collect garbage" reclaims the space of deleted address ranges, and the prototype editor no longer grows the database with every use

### Minor Improvements

* database: databases can be packed as several independent zstd frames (`PACK_ZSTD_FRAME_SIZE` in `ida.cfg`, in MB, default 32), so tools such as IDA Teams can decode them in parallel: checking out a 9 GB database went from 2.3 s to 0.3 s
* dsc: the region map of a dyld shared cache is built in linear time
* dwarf: memory usage is lower when loading binaries with a huge number of DIEs
* dwarf: debug sections are memory-mapped, which reduces memory usage
* dwarf: the per-DIE memory overhead is lower when loading binaries with many DIEs
* dwarf: new opt-in on-demand type loading for very large binaries
* rtti: analysis is faster; it used to slow down disproportionately on files with many C++ classes
* types: adding many names to a type library is faster
* tilib: parsing an enum with many members is faster
* names: creating names in a reopened database no longer gets slower the more names the database already contains
* parallel IDA instances no longer keep rebuilding the processor module cache
* a run of IDA without IDAPython no longer makes the next run reload every processor module
* regfinder: auto-analysis of huge functions with flattened control flow is much faster
* database: enabling an address range no longer rewrites the whole database
* names: name printing in `apply_regexes`/`qregsubst` is faster
* database: "collect garbage" also reclaims the space of deleted address ranges
* database: the function prototype editor no longer saves its cursor positions in the database, which grew it with every use
* flirt: signature files are read through a buffer instead of a byte at a time
* vd: building chains is faster (the block of a chain bit is checked in constant time)
* vd: rule CMB7 looks back at most 128 instructions for its `mov 0`, which bounds its cost
* vd: builtin patterns are rejected on the first block before a match is built, which saves time
* vd: leak checking counts live ctree items instead of copying their set, which saves time and memory
* vd: each expression type is checked for printability only once per decompilation
* vd: functions with long basic blocks decompile much faster: a function with one 5506-instruction basic block went from 2929 s to 148 s
* vd: batch decompilation no longer slows down quadratically with the number of decompiled functions
* vd: dont snapshot microcode without open microcode view during decompilation
* swift: the Swift identifier characters are set once per database instead of repeatedly
* analysis: the frame members a stack variable overlaps are looked up instead of all being copied
* pathfinder: expanding a large path segment no longer takes seconds
* xref graph: large graphs are much faster to open, grow and rebuild
* ldr: a long chain of thunks from a named function made the database grow to gigabytes
* kernel: a variable read by many instructions made analysis quadratic
* ui: filtering and selecting in large folder trees is much faster
* types: clang: every parse outside the persistent instance leaked its AST
* types: clang: the persistent instance grew without bound
* db: deleting all records of a netnode could leave some of them in the database

## Configuration, IDAPython, SDK & API <a href="#sdk" id="sdk"></a>

### Installation Manifests for Loaders, Processor Modules, Type Libraries, FLIRT Signatures, IDS Files and Themes

Loaders, processor modules, type libraries, FLIRT signatures, IDS files and themes can now be installed the way plugins are, as a directory that holds a manifest file. The manifest has the same shape as `ida-plugin.json`:

```json
{
  "IDAMetadataDescriptorVersion": 1,
  "loader": {
    "name": "my loader",
    "entryPoint": "my_ldr.py"
  }
}
```

* the manifest names are `ida-loader.json` (`loaders/`), `ida-proc.json` (`procs/`), `ida-til.json` (`til/`), `ida-sig.json` (`sig/`), `ida-ids.json` (`ids/`) and `ida-theme.json` (`themes/`); loaders and processor modules need an `entryPoint`, the other kinds do not
* a type library or signature directory can carry files for several processors: IDA searches `<dir>/pc/`, `<dir>/arm/` and so on, the same as in `til/` and `sig/`. A type library can also be in `<dir>/` itself; a signature must be in the processor subdirectory
* an extension pack bundles several kinds in one directory. Put an `ida-extension.json` manifest in `$IDAUSR/extensions/<pack>/`, and the extension directories in its `loaders/`, `procs/`, `til/`, `sig/`, `ids/`, `themes/` and `plugins/` subdirectories. IDA ignores other files in these subdirectories
* packaged type libraries and signatures appear in the "Available type libraries" and "Available signatures" lists, and packaged themes in the theme selector
* IDA searches in this order: `$IDAUSR/<kind>/`, the packs in `$IDAUSR/extensions/`, the directory in `IDATIL`, `IDASGN` or `IDAIDS`, `$IDADIR/<kind>/`, and the packs in `$IDADIR/extensions/`. In each directory, files installed the classic way come first, then the extension directories sorted by name. If two plugins, loaders or processor modules have the same name, IDA uses the first one. Names that differ only in case are the same name
* a plugin, loader or processor module directory gives IDA only its entry point. The other files in the directory, for example helper scripts, do not hide files that IDA searches for by name
* IDA looks for extensions one time per session. Restart IDA after you install an extension
* loaders, processor modules, type libraries, signatures, IDS files and themes can be installed as directories with an `ida-<kind>.json` manifest, like plugins

### New "Synthetic String" API

A plugin can now add strings that exist only in the code.

### New "License Inspection" API

The new `License` class (`license.hpp`; `ida_license.License` in IDAPython) lets a plugin query the active license (whether it is usable, its product and edition, its activation period, and the add-ons and features it covers) and control it (set the active license, check a license out and in, borrow and return a floating license); see the `licinfo` sample plugin and the `print_license_info.py` example.

### `COLOR_GROUP` is now `COLOR_SEMSPAN`

`COLOR_GROUP` is renamed `COLOR_SEMSPAN` ("semantics-bearing span"), which says what the tag is actually for: it groups a run of tagged text into a single unit — that is how a qualified name highlights as a whole — and carries semantics about it: a one-byte kind, plus an opaque payload of *variable size* that Hex-Rays reserves the right to grow in any release. Never assume a size for that header: step over it with `tag_skipcode()`/`tag_skipcodes()`/`tag_advance()`, and read it with `tag_get_semspan_kind()`. `COLOR_GROUP` stays as a deprecated alias; the accompanying `tag_semspan()`, `tag_semspan_off()`, `PRTYPE_SEMSPAN` and `GNCN_SEMSPAN` are new in 9.5.

### XrefsTo() Includes Pointers to Thumb Functions

In ARM Thumb and MIPS16 code, a pointer to a function is the function address + 1. `XrefsTo()` did not return the xrefs from these pointers. Now it does.

A pointer to `0x10121` makes the CPU run the code at `0x10120`, so it refers to the function at `0x10120`. Scripts that looked for the callers or users of a Thumb function missed these references.

Example: `sub_10120` is a Thumb function.

```
LOAD:00010102  BL   sub_10120              ; direct call: code xref to 10120
LOAD:0001010A  LDR  R1, =(sub_10120+1)     ; loads the function pointer: data xref to 10121
LOAD:00010138  DCD  sub_10120+1            ; the pointer stored in memory: data xref to 10121
```

The call refers to `0x10120`. The two pointers have bit 0 set to mark Thumb code, so they refer to `0x10121`.

Example: listing the xrefs in IDAPython.

```python
for x in idautils.XrefsTo(0x10120):
    print("%X -> %X" % (x.frm, x.to))
```

```
9.4:
10102 -> 10120

9.5:
10102 -> 10120
1010A -> 10121
10138 -> 10121
```

The xrefs to the exact address come first. For the pointers, `to` is `0x10121`, not the address you asked for.

To get the old behavior, pass the new `XREF_EXACT` flag.

Example: IDAPython.

```python
for x in idautils.XrefsTo(0x10120, ida_xref.XREF_EXACT):
    print("%X -> %X" % (x.frm, x.to))
# 10102 -> 10120
```

Example: C++.

```cpp
xrefblk_t xb;
for ( bool ok = xb.first_to(0x10120, XREF_EXACT); ok; ok = xb.next_to() )
  msg("%a -> %a\n", xb.from, xb.to);
// 10102 -> 10120
```

Other processors are not affected.

### Minor Changes

* dsc: `DSCU_USE_SEG_PREFIXES` (`dscu.cfg`) is honored for cache-image segment names
* macho: `USE_SEG_PREFIXES` is retired in favor of the more versatile `SEGNAME_FORMAT`, harmonized across kernelcaches, dyld shared caches and plain Mach-O; the old option is still honored for backwards compatibility
* hexagon: new `QDSP6_VALIDATE_DUPLEX` option
* hexagon: processor options can be set in `ida.cfg`
* the maximum stack frame size is configurable
* decompiler: `set_decompiler_timeout(msecs)` bounds a whole `decompile()` call (internal retries included) and fails with the new `MERR_TIMEOUT`; intended for headless and idalib runs, where there is no Cancel button
* decompiler: added save/restore APIs for split settings and for vararg call arguments
* decompiler: `decompile_many()` with a null output file decompiles to the cache only, and `VDRUN_RECURSIVE` is exported; from IDAPython: `ida_hexrays.decompile_many(None, [ea], ida_hexrays.VDRUN_RECURSIVE)`
* the length of string literal comments is configurable (`STRLIT_COMMENT_LENGTH`)
* `ev_sanitize_name` receives the kind of name being sanitized
* clang: the clang type parser is the default and is also used while loading
* new listing-export API (`export_listing`): renders disassembly, pseudocode and type listings as text or HTML; available to plugins, IDAPython and idalib
* decompiler: new class API. `get_classes()`, `get_class_info()`, `render_class()` and `render_member()` give a language-neutral view of the program's classes, their members, and the class view's rendering of them; available to C++ plugins and IDAPython (see the `list_classes.py` example)
* new `qgetpid()` returns the id of the current process
* try block structures can be compared with `==` and `!=`
* idalib: an old `.idb` opened with idalib is converted to `.i64` automatically, and the session continues on the converted database
* sdk: `qvector` has a new `append(first, last)` to append an element range
* added `NTF_AUTONAME` to save a udt under a name built from its member types
* added `tinfo_t::create_tuple()` to create and save a tuple from member types
* installer: do not show vc\_redist error message when a newer version is already installed

### Bugfixes

* sdk: `qtree.hpp` could not be compiled with GCC 8.x
* sdk: `qustrncpy()` cut a 4-byte UTF-8 character that fit in the buffer
* idapython: objects a script created, such as hooks, stayed alive after the script ended
* idapython: raising `SystemExit` from the CLI closed IDA
* idapython: `ask_file` with empty string arguments crashed IDA
* idalib: a failed `open_database` terminated the host process
* plugins: when two plugins in subdirectories of `plugins/` had the same name, the order of the files on disk selected the plugin that IDA loaded
* idapython: a processor module script could not import a Python module installed next to it
* installer: windows: a message said the Visual C++ redistributable installation failed when a newer version was already installed
* loaders built with the SDK's CMake files could corrupt the heap on loader\_failure() on Windows
* IDAPython: `IDP_Hooks.ev_decorate_name` received a truncated calling convention

## Network & Security <a href="#network" id="network"></a>

### Clear Answers When a License, Lumina or Vault Server Misbehaves

* a failed connection names the server (`host:port`) and leads with the cause instead of a bare transport error, and a missing license is reported as "license X is not available on this server". The License Manager and the `lsadm`, `hv` and `lc` tools share the same classification
* IDA no longer freezes when the license or Lumina server stops responding — during work, on exit, or during cloud decompilation: blocking network operations are bounded or can be cancelled
* macOS: IDA uses the TLS-1.3-capable LibreSSL the system ships, so it connects to servers that require TLS 1.3 and to FIPS servers that require the Extended Master Secret extension (the handshake used to fail with alert 80)

### Minor Improvements

* security: Linux builds are hardened with full RELRO and PLT-free linkage, making them more resistant to memory-corruption exploits


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.hex-rays.com/release-notes/9_5.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
