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:ICFshould 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:
Visual Studio¶
- Project Properties → Linker → Optimization
- Set "Enable COMDAT Folding" to "Yes (/OPT:ICF)"
- Ensure "Link Incrementally" is set to "No (/INCREMENTAL:NO)"
CMake¶
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)
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