Re: pahole treats embedded structures a holes
Arnaldo Carvalho de Melo <[email protected]> Fri, 5 Jun 2026 16:28:18 -0300
| Newsgroups | org.kernel.vger.dwarves |
|---|---|
| Message-ID | <aiMjUoE_CPn7hJtv@x1> |
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 <[email protected]> ----- Date: Mon, 1 Jun 2026 12:18:58 -0300 From: Arnaldo Carvalho de Melo <[email protected]> To: Christoph Hellwig <[email protected]> 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 -----