Why did GCC drop the progbits flag in .section directives for objects in .data, .rodata?

2026-08-26

Stack Overflow: View Question

Tags: assembly, gcc, memory, elf, advice

Score: 0 | Views: 108

The asker compiles a trivial translation unit containing one initialized variable and one const, using -fdata-sections, and inspects the generated assembly. They notice GCC emits:

    .section    .data.i,"aw"
    .section    .rodata.c,"a"

Rather than the "full" form one might expect:

    .section    .data.i,"aw",@progbits
    .section    .rodata.c,"a",@progbits

Why did GCC stop emitting the @progbits type argument for these sections?

Why this is interesting. On the surface it looks cosmetic — GNU as will infer @progbits for .data* and .rodata* just fine, so the resulting object file is identical. But the question touches something subtle about how the assembler classifies sections. GAS maintains a table of "well-known" section names (.text, .data, .rodata, .bss, .tbss, .tdata, etc.). For those names — and for names beginning with those prefixes when -fdata-sections/-ffunction-sections is in play — the type is implied. Explicitly repeating @progbits is redundant and slightly increases the size of the emitted assembly, which matters for a compiler that emits enormous .s files through a pipe to the assembler.

The direction toward an answer. Search the GCC source (gcc/varasm.cc, function default_elf_asm_named_section). That function decides whether to emit the flags and type on a .section directive. It has logic that suppresses the type when the assembler is guaranteed to infer it, and it also handles the special case of .rodata — which is a SHF_ALLOC-only section (flag "a", no w or x), where @progbits is the only sensible type. The behavior change likely traces back to a commit that trimmed redundant type arguments to shrink assembly output; git-blaming default_elf_asm_named_section and looking at the GCC changelogs around the version transition (the asker uses 13.2.1) will give the definitive reason. Cross-referencing the GAS manual's section on the ELF flavor of .section confirms that omitting the type is valid for well-known names.

Gotchas. The inference only works for GNU as with ELF targets; other assemblers (LLVM's integrated assembler, some legacy toolchains) may be pickier. It also breaks down for sections whose name doesn't start with a well-known prefix — try .section .weirdname,"aw" and you'll get @progbits defaulted, but the semantics can differ per target. And for sections that could be @nobits (like .bss.*), the flag string must not contain "w" alone without triggering the right default — this is why .bss handling in the same function has its own branch.

The challenge: A seemingly cosmetic GCC output change reveals a small but principled contract between compiler and assembler about which ELF section attributes are implied versus explicit.

All newsletters