All of lore.kernel.org
 help / color / mirror / Atom feed
* pahole treats embedded structures a holes
@ 2026-05-28  5:11 Christoph Hellwig
  2026-05-28 13:39 ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 7+ messages in thread
From: Christoph Hellwig @ 2026-05-28  5:11 UTC (permalink / raw)
  To: dwarves

[-- Attachment #1: Type: text/plain, Size: 969 bytes --]

Hi all,

this is a pretty old bug as far as I can tell, but I finally tried to
track it down and failed.

When running dwarves, both the package in Debian testing and a build of
todays git tree on Debian testing, it treats a lot of C structures
embedded into others as holes instead of having a size for them.  I
think this generally structures defined in other header files and
not the file containing the offending struct.

E.g. if I run pahole on fs/xfs/xfs_buf.o on a current mainline kernel,
the output for struct xfs_buf starts like this:

struct xfs_buf {
        struct rhash_head          b_rhash_head;         /*     0     0 */

        /* XXX 8 bytes hole, try to pack */

        xfs_daddr_t                b_rhash_key;          /*     8     8 */

struct rhash_head is a single pointer, so 8 bytes on x86-64, and
xfs_daddr_t is also a 64-bit type, so both the 0 size and the 8
byte hole are clearly wrong.  The kernel .config is attached in case
it matter.

[-- Attachment #2: config.gz --]
[-- Type: application/x-gzip, Size: 26863 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread
* Re: pahole treats embedded structures a holes
@ 2026-06-05 19:28 Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 7+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-06-05 19:28 UTC (permalink / raw)
  To: dwarves

FYI and documentation. I'll work on looking at the DW_AT_producer tag
for those compiler options to show in the pretty printing output, as
well as checking potential implications for BTF generation, but I think
that one will end up being harmless because of the combination of all
DWARF CUs the types suppressed by CU would eventually be resolved.

- Arnaldo

----- Forwarded message from Arnaldo Carvalho de Melo <acme@kernel.org> -----

Date: Mon, 1 Jun 2026 12:18:58 -0300
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Christoph Hellwig <hch@lst.de>
Subject: Re: pahole treats embedded structures a holes
Message-ID: <ah2i4lHbSgilDxQd@x1>

On Sat, May 30, 2026 at 05:22:20AM +0200, Christoph Hellwig wrote:
> Here is a compressed xfs_buf.o.  I don't think it's the same as before,
> but it shows the same symptoms.

TIL: -femit-struct-debug-baseonly

TLDR; you enabled CONFIG_DEBUG_INFO_REDUCED while distros use:

acme@x1:~/git/linux$ grep CONFIG_DEBUG_INFO_ /lib/modules/`uname -r`/config
# CONFIG_DEBUG_INFO_NONE is not set
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
# CONFIG_DEBUG_INFO_DWARF4 is not set
# CONFIG_DEBUG_INFO_DWARF5 is not set
# CONFIG_DEBUG_INFO_REDUCED is not set
CONFIG_DEBUG_INFO_COMPRESSED_NONE=y
# CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set
# CONFIG_DEBUG_INFO_SPLIT is not set
CONFIG_DEBUG_INFO_BTF=y
CONFIG_DEBUG_INFO_BTF_MODULES=y
acme@x1:~/git/linux$

I'm adding a TODO entry to notice that and add a comment at that point
stating that the type for a embedded struct wasn't found and that the
user probably is using -femit-struct-debug-baseonly and maybe
CONFIG_DEBUG_INFO_REDUCED.

Please consider replying with this message to the mailing list to leave
this documented in the archives :-)

- Arnaldo

Longer analysis:

acme@x1:~$ pahole -C xfs_buf xfs_buf.o  | head
struct xfs_buf {
	struct rhash_head          b_rhash_head;         /*     0     0 */

	/* XXX 8 bytes hole, try to pack */

	xfs_daddr_t                b_rhash_key;          /*     8     8 */
	int                        b_length;             /*    16     4 */

	/* XXX 4 bytes hole, try to pack */

acme@x1:~$ pahole -C b_rhash_head xfs_buf.o 
pahole: type 'b_rhash_head' not found
acme@x1:~$ pahole -C xfs_buf xfs_buf.o  | head
struct xfs_buf {
	struct rhash_head          b_rhash_head;         /*     0     0 */

	/* XXX 8 bytes hole, try to pack */

	xfs_daddr_t                b_rhash_key;          /*     8     8 */
	int                        b_length;             /*    16     4 */

	/* XXX 4 bytes hole, try to pack */

acme@x1:~$ pahole -C rhash_head xfs_buf.o 
pahole: type 'rhash_head' not found
acme@x1:~$

acme@x1:~$ readelf -wi xfs_buf.o | grep DW_AT_producer
    <d>   DW_AT_producer    : (indirect string, offset: 0x28e6): GNU C11 15.2.0 -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -mno-sse4a -m64 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -march=x86-64 -mtune=generic -mno-red-zone -mcmodel=kernel -mstack-protector-guard-reg=gs -mstack-protector-guard-symbol=__ref_stack_chk_guard -mindirect-branch=thunk-extern -mindirect-branch-register -mindirect-branch-cs-prefix -mfunction-return=thunk-extern -g -O2 -std=gnu11 -fshort-wchar -funsigned-char -fno-common -fno-PIE -fno-strict-aliasing -fms-extensions -fcf-protection=branch -falign-jumps=1 -falign-loops=1 -fno-asynchronous-unwind-tables -fno-jump-tables -fpatchable-function-entry=16,16 -fno-delete-null-pointer-checks -fno-allow-store-data-races -fstack-protector-strong -fomit-frame-pointer -fzero-init-padding-bits=all -fno-stack-clash-protection -fmin-function-alignment=16 -fstrict-flex-arrays=3 -fno-strict-overflow -fstack-check=no -fconserve-stack -fno-builtin-wcslen -fno-var-tracking -femit-struct-debug-baseonly
acme@x1:~$

acme@x1:~/git/linux$ git grep -B4 -A4 -- -femit-struct-debug-baseonly
rust/Makefile-  -mno-pointers-to-nested-functions -mno-string \
rust/Makefile-  -mno-strict-align -mstrict-align -mdirect-extern-access \
rust/Makefile-  -mexplicit-relocs -mno-check-zero-division \
rust/Makefile-  -fconserve-stack -falign-jumps=% -falign-loops=% \
rust/Makefile:  -femit-struct-debug-baseonly -fno-ipa-cp-clone -fno-ipa-sra \
rust/Makefile-  -fno-partial-inlining -fplugin-arg-arm_ssp_per_task_plugin-% \
rust/Makefile-  -fno-reorder-blocks -fno-allow-store-data-races -fasan-shadow-offset=% \
rust/Makefile-  -fzero-call-used-regs=% -fno-stack-clash-protection \
rust/Makefile-  -fno-inline-functions-called-once -fsanitize=bounds-strict \
--
scripts/Makefile.debug-ifdef CONFIG_DEBUG_INFO_REDUCED
scripts/Makefile.debug-DEBUG_CFLAGS     += -fno-var-tracking
scripts/Makefile.debug-DEBUG_RUSTFLAGS  += -Cdebuginfo=1
scripts/Makefile.debug-ifdef CONFIG_CC_IS_GCC
scripts/Makefile.debug:DEBUG_CFLAGS     += -femit-struct-debug-baseonly
scripts/Makefile.debug-endif
scripts/Makefile.debug-else
scripts/Makefile.debug-DEBUG_RUSTFLAGS  += -Cdebuginfo=2
scripts/Makefile.debug-endif
acme@x1:~/git/linux$

----- 8< -----
-femit-struct-debug-baseonly is a GCC (GNU Compiler Collection)
command-line flag used to drastically reduce the size of object files by
limiting the amount of debug information generated for structures,
unions, and classes.

It works by strictly filtering which type definitions are included in
the final DWARF debug symbols based on where those types are
declared.

How it Works

When you compile a source file (e.g., main.c), the compiler normally
emits debug information for all types used or declared within that file,
including those from deeply nested external header files.

With -femit-struct-debug-baseonly enabled, GCC uses aggressive filtering
rules:

Matches Base File Name: Debug information is only generated for
structs/unions/classes if the base name of the file where the type is
declared matches the base name of the file being compiled.

Practical Example:

If you are compiling foo.c, debug symbols will only be generated for
types declared directly inside foo.c and its direct companion header
foo.h. Types declared in other included headers (like standard_lib.h)
are completely ignored.

Key Benefits

Smaller Binaries:

It severely reduces the storage footprint of debug ELF and object files.

Faster Link Times:

Less debug information means linkers have less data to process and
deduplicate.

Faster Debugger Loading:

Debuggers like GDB or IDE symbol loaders can load the project
significantly faster.

Caveats & Constraints

Limited Debugging Visibility:

Because it aggressively strips type data, your debugger might not
recognize or be able to pretty-print structures declared in external
files or libraries during a live debugging session.

Format Restriction: This flag exclusively functions with DWARF debug
output format.

Alternative Flags: It is a stricter, more aggressive variant of
-femit-struct-debug-reduced.

If you require fine-grained control, you can instead use
-femit-struct-debug-detailed.

----- 8< -----

----- End forwarded message -----

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-06-05 19:28 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-28  5:11 pahole treats embedded structures a holes Christoph Hellwig
2026-05-28 13:39 ` Arnaldo Carvalho de Melo
2026-05-28 13:58   ` Christoph Hellwig
2026-05-28 19:48     ` Arnaldo Carvalho de Melo
2026-05-29  4:02       ` Christoph Hellwig
2026-05-29 19:28         ` Arnaldo Carvalho de Melo
  -- strict thread matches above, loose matches on Subject: below --
2026-06-05 19:28 Arnaldo Carvalho de Melo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.