Search notes:

Using pahole for Linux sources

Prepare a kernel with debug information

In order to use pahole on the compiled Linux sources, the Kernel must be compiled with debug information.
First, we need to have a (shallow)copy of the sources:
git clone --depth 1 -b master https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git linux
cd linux
We then create a default configuration …
make defconfig
… and request that debug information is added to the built kernel:
scripts/config --enable debug_info_dwarf_toolchain_default
yes '' | make oldconfig
Finally, we built the kernel
make -j$(nproc)

Using pahole

Show the layout of a struct

The -C options specifies the name of the struct which we want to investigate:
$ pahole vmlinux -C boot_params
struct boot_params {
        struct screen_info         screen_info;          /*     0    64 */
        /* --- cacheline 1 boundary (64 bytes) --- */
        struct apm_bios_info       apm_bios_info;        /*    64    20 */
        __u8                       _pad2[4];             /*    84     4 */
        __u64                      tboot_addr;           /*    88     8 */
        struct ist_info            ist_info;             /*    96    16 */

    … output snipped …

        struct setup_header        hdr;                  /*   497   123 */
        /* --- cacheline 9 boundary (576 bytes) was 44 bytes ago --- */
        __u8                       _pad7[36];            /*   620    36 */
        /* --- cacheline 10 boundary (640 bytes) was 16 bytes ago --- */
        __u32                      edd_mbr_sig_buffer[16]; /*   656    64 */
        /* --- cacheline 11 boundary (704 bytes) was 16 bytes ago --- */
        struct boot_e820_entry     e820_table[128];      /*   720  2560 */
        /* --- cacheline 51 boundary (3264 bytes) was 16 bytes ago --- */
        __u8                       _pad8[48];            /*  3280    48 */
        /* --- cacheline 52 boundary (3328 bytes) --- */
        struct edd_info            eddbuf[6];            /*  3328   492 */
        /* --- cacheline 59 boundary (3776 bytes) was 44 bytes ago --- */
        __u8                       _pad9[276];           /*  3820   276 */

        /* size: 4096, cachelines: 64, members: 35 */
} __attribute__((__packed__));
Adding q shows the struct with less clutter and arguably more readable:
$ pahole vmlinux -C boot_params -q
struct boot_params {
        struct screen_info         screen_info;
        struct apm_bios_info       apm_bios_info;
        __u8                       _pad2[4];
        __u64                      tboot_addr;
        struct ist_info            ist_info;

    … output snipped …

        struct setup_header        hdr;
        __u8                       _pad7[36];
        __u32                      edd_mbr_sig_buffer[16];
        struct boot_e820_entry     e820_table[128];
        __u8                       _pad8[48];
        struct edd_info            eddbuf[6];
        __u8                       _pad9[276];
} __attribute__((__packed__));

Show file and line number where struct was defined

Using -I shows where a struct is defined and used:
$ pahole vmlinux -C boot_params -q -I
/* Used at: arch/x86/kernel/head64.c */
/* <2c290e> ./arch/x86/include/uapi/asm/bootparam.h:185 */
struct boot_params {
        struct screen_info         screen_info;
        struct apm_bios_info       apm_bios_info;

    … output snipped …

} __attribute__((__packed__));

Expand members

If the examined struct contains nested structs, the -E option allows to expand them recursively:
$ pahole vmlinux -C boot_params -q -E
struct boot_params {
        struct screen_info {
                /* typedef __u8 */ unsigned char      orig_x;
                /* typedef __u8 */ unsigned char      orig_y;
                /* typedef __u16 */ short unsigned int ext_mem_k;

…

Find structs with a given embedded struct

The -i (or --contains) option displays structs that contain a given struct:
$ pahole vmlinux -i setup_header
boot_params

Index