AD3004: GenerateRequiredSymbolFormat¶
Summary¶
| Property | Value |
|---|---|
| ID | AD3004 |
| Name | GenerateRequiredSymbolFormat |
| Category | Correctness |
| Severity | Warning |
| Applies to | ELF (Linux/Unix) |
Description¶
ELF binaries should include debug symbols in DWARF format for effective debugging and security analysis. Modern DWARF versions (4 and 5) provide better debugging information and are recommended over older formats.
How It Works¶
The rule parses DWARF debug sections in the binary and checks:
- Presence of DWARF debug information
- DWARF version number (4+ recommended)
- Compilation unit information
Why This Matters¶
Debug symbols aren't just for development—they're essential for security analysis, incident response, and crash investigation. Proper DWARF symbols can mean the difference between understanding an attack and being blind to it.
Security Analysis Benefits¶
Symbols enable deeper security analysis:
| Analysis Type | Without Symbols | With Symbols |
|---|---|---|
| Crash triage | Raw addresses | Function names, line numbers |
| Vulnerability assessment | Reverse engineering needed | Direct source correlation |
| Fuzzer output | Hard to interpret | Clear crash locations |
| Static analysis | Limited | Full variable/type info |
Incident Response Speed¶
Crash Report Without Symbols:
SIGSEGV at 0x55a3b8c01234
Stack: 0x55a3b8c00890 -> 0x55a3b8c00456 -> 0x55a3b8c00123
Time to diagnose: Hours/days of reverse engineering
Crash Report With Symbols:
SIGSEGV at process_user_input+0x42 (input.c:156)
Stack: validate_header (parser.c:89)
-> parse_request (parser.c:234)
-> main (server.c:45)
Time to diagnose: Minutes
DWARF Version Comparison¶
| DWARF Version | Features | Recommendation |
|---|---|---|
| DWARF 2 | Basic debug info | Outdated |
| DWARF 3 | Better C++ support | Outdated |
| DWARF 4 | Better optimization debug | Good (widely compatible) |
| DWARF 5 | Split DWARF, better strings | Best (if toolchain supports) |
Symbol Stripping Strategy¶
For production, use separate debug files:
# Build with symbols
gcc -g -o binary source.c
# Extract debug info
objcopy --only-keep-debug binary binary.debug
# Strip binary (keep build-id link)
objcopy --strip-debug --add-gnu-debuglink=binary.debug binary
# Result:
# binary - Small, for deployment
# binary.debug - Symbols, for debugging
Security Research Value¶
Vulnerability researchers rely on symbols:
| Task | Symbol Benefit |
|---|---|
| Finding vulnerable functions | Named function searches |
| Understanding data structures | Type information |
| Tracing data flow | Variable names and scope |
| Patch analysis | Diffing named entities |
Performance Profiling¶
Symbols enable meaningful profiling:
Without symbols:
45% - 0x400123
30% - 0x400456
25% - 0x400789
With symbols:
45% - encrypt_block
30% - memcpy (from glibc)
25% - validate_input
Storage and Distribution¶
| Approach | Binary Size | Debug Available |
|---|---|---|
| No debug info | Smallest | No |
| Embedded DWARF | Largest | Always |
| Split DWARF (.dwo) | Small + debug files | With files |
| Debuginfod server | Small | Network access |
- Debugging: Proper symbols enable effective debugging
- Crash analysis: Better stack traces and variable inspection
- Security research: Easier vulnerability analysis
- Incident response: Faster root cause analysis
- Profiling: Better performance analysis
Resolution¶
Generate DWARF Debug Info¶
GCC/Clang:
# Generate DWARF 4 (widely compatible)
gcc -g -gdwarf-4 source.c -o binary
# Generate DWARF 5 (latest, more features)
gcc -g -gdwarf-5 source.c -o binary
# Default (usually DWARF 4 or 5)
gcc -g source.c -o binary
Debug Levels¶
# Level 1: Minimal (line numbers, function names)
gcc -g1 source.c -o binary
# Level 2: Default (includes local variables)
gcc -g2 source.c -o binary # Same as -g
# Level 3: Maximum (includes macro definitions)
gcc -g3 source.c -o binary
CMake¶
Separate Debug Files¶
For release binaries, strip but keep debug info separately:
# Compile with debug info
gcc -g source.c -o binary
# Extract debug symbols
objcopy --only-keep-debug binary binary.debug
# Strip the binary
strip binary
# Add debug link
objcopy --add-gnu-debuglink=binary.debug binary
When to Suppress¶
This rule may be suppressed for:
- Release builds: Intentionally stripped binaries
- Size constraints: Embedded systems with limited storage
- Security by obscurity: (Not recommended) Hiding symbol information
- Third-party binaries: When you don't control the build
Caveats¶
- Debug info significantly increases file size
- Some distributions use separate debug packages
- DWARF 5 requires newer tools
DWARF Versions¶
| Version | Introduced | Key Features |
|---|---|---|
| DWARF 2 | 1993 | Basic format |
| DWARF 3 | 2005 | Better C++ support |
| DWARF 4 | 2010 | Types section, improved size |
| DWARF 5 | 2017 | Split DWARF, better compression |
Checking DWARF Info¶
# Check for DWARF sections
readelf --debug-dump=info binary | head
# Check DWARF version
readelf --debug-dump=info binary | grep "Version:"
# List compilation units
readelf --debug-dump=info binary | grep "Compilation Unit"
# Using dwarfdump
dwarfdump binary
Split DWARF (DWARF 5)¶
For faster builds, use split DWARF: