Skip to content

AD6004: EnableComdatFolding

Summary

Property Value
ID AD6004
Name EnableComdatFolding
Category Performance
Severity Warning
Applies to PE (Windows)

Description

This rule checks that PE binaries were linked with COMDAT folding (/OPT:ICF) enabled. COMDAT folding merges identical functions (Identical COMDAT Folding), reducing binary size and potentially improving cache performance.

Why This Matters

COMDAT folding (Identical COMDAT Folding) merges functions with identical machine code, significantly reducing binary size especially in C++ template-heavy codebases where template instantiation creates many duplicate functions.

Template Bloat Problem

// Template creates separate function for each type:
template<typename T>
void process(T val) { /* same code */ }

process<int>(1);     // Instantiates process<int>
process<long>(2);    // Instantiates process<long> (identical code!)
process<size_t>(3);  // Instantiates process<size_t> (identical code!)

// Without ICF: 3 identical functions in binary
// With ICF: 1 function, 3 names point to it

Size Reduction

Binary Type Typical Savings
C code 1-5%
C++ (simple) 5-15%
C++ (templates) 10-30%
Header-only libs 15-40%

How ICF Works

Function A: 48 89 e5 48 83 ec 10 ...  (machine code)
Function B: 48 89 e5 48 83 ec 10 ...  (identical!)

Without ICF:
  A at 0x1000
  B at 0x2000
  Total: 2 copies

With ICF:
  A at 0x1000
  B is alias to 0x1000
  Total: 1 copy

Security Benefit

Smaller binaries = fewer ROP gadgets:

With ICF disabled:
  100 identical functions = 100 copies of gadgets

With ICF enabled:
  100 identical functions = 1 copy of gadgets
  99 fewer exploitation opportunities

Cache Efficiency

Identical functions folded:
  - Less code total
  - Better I-cache utilization
  - Fewer page faults
  - Faster execution

Compatibility Notes

Scenario ICF Safe
Normal functions Yes
Function pointer identity May break (rare)
SEH handlers Yes
Debug builds Don't use (debugging)
  • Smaller binaries: Identical functions are merged into one
  • Template bloat reduction: Especially beneficial for C++ template-heavy code
  • Cache efficiency: Less code means better instruction cache utilization
  • Release build indicator: /OPT:ICF should be enabled for release builds

How to Fix

Enable COMDAT folding

# Link with ICF enabled
link /OPT:ICF myapp.obj

# Full release optimization
link /OPT:REF /OPT:ICF myapp.obj

Disable incremental linking (required)

COMDAT folding is incompatible with incremental linking:

link /INCREMENTAL:NO /OPT:ICF myapp.obj

Visual Studio

  1. Project Properties → Linker → Optimization
  2. Set "Enable COMDAT Folding" to "Yes (/OPT:ICF)"
  3. Ensure "Link Incrementally" is set to "No (/INCREMENTAL:NO)"

CMake

if(MSVC)
    set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /OPT:ICF")
endif()

Detection Method

aldur detects COMDAT folding by checking for the presence of the .textbss section, which indicates incremental linking. If .textbss is present, COMDAT folding is disabled.

Example

Warning: COMDAT folding not enabled

Binary appears to use incremental linking (.textbss section present).
COMDAT folding is disabled. Link with /INCREMENTAL:NO /OPT:ICF for release builds.

Pass: COMDAT folding enabled (no incremental linking)

Binary does not use incremental linking. COMDAT folding optimization is available.

Trade-offs

  • Debugging: Folded functions share the same address, which can complicate debugging
  • Build time: ICF increases link time (but decreases binary size)
  • Address uniqueness: Function pointer comparisons may behave unexpectedly

See Also