Skip to content

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:

  1. Presence of DWARF debug information
  2. DWARF version number (4+ recommended)
  3. 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

# For Debug builds
set(CMAKE_BUILD_TYPE Debug)

# Or explicitly
add_compile_options(-g -gdwarf-4)

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:

gcc -g -gsplit-dwarf source.c -o binary
# Creates binary and binary.dwo

References