Re: pahole treats embedded structures a holes
Arnaldo Carvalho de Melo <[email protected]> Thu, 28 May 2026 10:39:34 -0300
| Newsgroups | org.kernel.vger.dwarves |
|---|---|
| Message-ID | <ahhFlsCJzkxLt3M6@x1> |
On Thu, May 28, 2026 at 07:11:52AM +0200, Christoph Hellwig wrote:
> 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.
Starting from using the BTF info, that becomes available thru sysfs as
soon as we load the xfs kernel module:
acme@x1:~$ ls -la /sys/kernel/btf/xfs
ls: cannot access '/sys/kernel/btf/xfs': No such file or directory
acme@x1:~$ sudo modprobe xfs
acme@x1:~$ ls -la /sys/kernel/btf/xfs
-r--r--r--. 1 root root 630917 May 28 10:33 /sys/kernel/btf/xfs
acme@x1:~$
acme@x1:~$ pahole --sizes /sys/kernel/btf/xfs | sort -nr -k2 | grep xfs | head
xfs_mount 4032 8
xfs_dquot_acct 1320 0
xfs_cil_ctx 1240 2
xfsstats 1088 0
__xfsstats 1088 0
xfs_inode 984 2
xfs_quotainfo 552 1
xfs_dquot 536 3
xfs_perag 480 4
xfs_da_state 480 1
acme@x1:~$
Now to the 'xfs_buf' struct:
acme@x1:~$ pahole /sys/kernel/btf/xfs -C xfs_buf | head
struct xfs_buf {
struct rhash_head b_rhash_head; /* 0 8 */
xfs_daddr_t b_rhash_key; /* 8 8 */
int b_length; /* 16 4 */
unsigned int b_hold; /* 20 4 */
atomic_t b_lru_ref; /* 24 4 */
xfs_buf_flags_t b_flags; /* 28 4 */
struct semaphore b_sema; /* 32 24 */
struct list_head b_lru; /* 56 16 */
/* --- cacheline 1 boundary (64 bytes) was 8 bytes ago --- */
acme@x1:~$
Seems ok, expanding it:
acme@x1:~$ pahole -E /sys/kernel/btf/xfs -C xfs_buf | head
struct xfs_buf {
struct rhash_head {
struct rhash_head * next; /* 0 8 */
} b_rhash_head; /* 0 8 */
/* typedef xfs_daddr_t -> __s64 */ long long int b_rhash_key; /* 8 8 */
int b_length; /* 16 4 */
unsigned int b_hold; /* 20 4 */
/* typedef atomic_t */ struct {
int counter; /* 24 4 */
} b_lru_ref; /* 24 4 */
acme@x1:~$
Looks ok and with your description of the struct, a pointer, 8 bytes,
etc.
Now I'll try with a fresh kernel build, with a default fedora kernel
config, will take a while, but having access to a separate .o file from
the kernel build process, with just DWARF info is what we need to get to
the state you're in, that should work, lets see why you're getting the
unsatisfactory results you're getting, maybe we need further info about
compiler versions, etc, but lets see...
- Arnaldo