Skip site navigation (1)Skip section navigation (2)

  
 
  

home | help
pahole(1)			     dwarves			       pahole(1)

NAME
     pahole  -	Shows,	manipulates  data structure layout and pretty prints raw
     data.

SYNOPSIS
     pahole [options] files

DESCRIPTION
     pahole shows data structure layouts encoded in debugging  information  for-
     mats, DWARF, CTF and BTF being supported.

     This  is  useful  for, among other things: optimizing important data struc-
     tures by reducing its size, figuring out what is the field  sitting  at  an
     offset  from  the	start of a data structure, investigating ABI changes and
     more generally understanding a new codebase you have to work with.

     It also uses these structure layouts to pretty print data feed to its stan-
     dard input, e.g.:

     $ pahole --header elf64_hdr --prettify /lib/modules/5.8.0-rc6+/build/vmlinux
     {
	  .e_ident = { 127, 69, 76, 70, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	  .e_type = 2,
	  .e_machine = 62,
	  .e_version = 1,
	  .e_entry = 16777216,
	  .e_phoff = 64,
	  .e_shoff = 604653784,
	  .e_flags = 0,
	  .e_ehsize = 64,
	  .e_phentsize = 56,
	  .e_phnum = 5,
	  .e_shentsize = 64,
	  .e_shnum = 80,
	  .e_shstrndx = 79,
     },
     $

     See the PRETTY PRINTING section for further examples and documentation.

     The files must have associated debugging information.  This information may
     be inside the file itself, in ELF sections, or in another file.

     One way to have this information is to specify the -g option  to  the  com-
     piler when building it. When this is done the information will be stored in
     an  ELF  section.	For  the  DWARF debugging information format this, adds,
     among others, the .debug_info ELF section. For CTF it is found in just  one
     ELF section, .SUNW_ctf. BTF comes in at least the .BTF ELF section, and may
     come also with the .BTF.ext ELF section.

     The  debuginfo packages available in most Linux distributions are also sup-
     ported by pahole, where the debugging information is available in	a  sepa-
     rate file.

     By default, pahole shows the layout of all named structs in the files spec-
     ified.

     If no files are specified, then it will look if the /sys/kernel/btf/vmlinux
     is  present, using the BTF information present in it about the running ker-
     nel, i.e. this works:

     $ pahole list_head
     struct list_head {
	  struct list_head *	     next;		   /*	  0	8 */
	  struct list_head *	     prev;		   /*	  8	8 */

	  /* size: 16, cachelines: 1, members: 2 */
	  /* last cacheline: 16 bytes */
     };
     $
     It is possible to override the  /sys/kernel/btf/vmlinux  file  location  by
     setting  the  PAHOLE_VMLINUX_BTF_FILENAME environment variable. This may be
     useful for testing, scripting when using a different BTF for vmlinux.  Used
     in the pahole regression tests.

     If  BTF  is  not present and no file is passed, then a vmlinux that matches
     the build-id for the running kernel will be looked up in the usual  places,
     including	where  the  kernel  debuginfo packages put it, looking for DWARF
     info instead.

     See the EXAMPLES section for more usage suggestions.

     It also pretty prints whatever is fed to its standard input,  according  to
     the type specified, see the EXAMPLE session.

     Use --count to state how many records should be pretty printed.

OPTIONS
     pahole supports the following options.

     -C, --class_name=CLASS_NAMES
	    Show just these classes. This can be a comma separated list of class
	    names or file URLs (e.g.: file://class_list.txt)

     -c, --cacheline_size=SIZE
	    Set cacheline size to SIZE bytes.

     --sort
	    Sort  the output by type name, maybe this will grow to allow sorting
	    by other criteria.

	    This is mostly needed so that pretty printing from BTF and DWARF can
	    be comparable when using using multiple threads to load DWARF  data,
	    when  the  order that the types in the compile units is processed is
	    not deterministic.

     --compile
	    Generate compileable code, with all definitions for all types, i.e.:

     $ pahole --compile > vmlinux.h

     Produces a header that can be included in a C source file and built. In the
     example provided it will use the BTF info if available, otherwise will look
     for a DWARF file matching the running kernel build-id.

     --skip_emitting_atomic_typedefs
	    Do not emit 'typedef _Atomic int atomic_int'  &  friends  when  used
	    with  options  like --compile. Use it if the compiler provides these
	    already, as of circa 2022 with gcc 12.2.1 those are not  encoded  in
	    DWARF so to generate compilable code we need emit those typedefs for
	    the  atomic types used in the data structures being emitted from de-
	    bugging information.

     --count=COUNT
	    Pretty print the first COUNT records from input.

     --skip=COUNT
	    Skip COUNT input records.

     -E, --expand_types
	    Expand class members. Useful to find in what member of inner structs
	    where an offset from the beginning of a struct is.

     -F, --format_path
	    Allows specifying a list of debugging  formats  to	try,  in  order.
	    Right now this includes "btf", "ctf" and "dwarf". The default format
	    path used is equivalent to "-F dwarf,btf,ctf".

     --hashbits=BITS
	    Allows specifying the number of bits for the debugging format loader
	    to	use.   The  only one affected so far is the "dwarf" one, its de-
	    fault now is 15, the maximum for it is now 21 bits. Tweak it to  see
	    if	it improves performance as the kernel evolves and more types and
	    functions have to be loaded.

     --hex  Print offsets and sizes in hexadecimal.

     -r, --rel_offset
	    Show relative offsets of members in inner structs.

     -p, --expand_pointers
	    Expand class pointer members.

     -R, --reorganize
	    Reorganize struct, demoting and combining bitfields, moving  members
	    to remove alignment holes and padding.

     -S, --show_reorg_steps
	    Show the struct layout at each reorganization step.

     -i, --contains=CLASS_NAME
	    Show classes that contains CLASS_NAME.

     --contains_enumerator=ENUMERATOR_NAME
	    Show enumeration that contains ENUMERATOR_NAME.

       $ pahole --contains_enumerator S_VERSION
       enum file_time_flags {
	    S_ATIME   = 1,
	    S_MTIME   = 2,
	    S_CTIME   = 4,
	    S_VERSION = 8,
       }
       $

     -a, --anon_include
	    Include anonymous classes.

     -A, --nested_anon_include
	    Include nested (inside other structs) anonymous classes.

     -B, --bit_holes=NR_HOLES
	    Show only structs at least NR_HOLES bit holes.

     -d, --recursive
	    Recursive mode, affects several other flags.

     -D, --decl_exclude=PREFIX
	    exclude classes declared in files with PREFIX.

     -f, --find_pointers_to=CLASS_NAME
	    Find pointers to CLASS_NAME.

     -H, --holes=NR_HOLES
	    Show only structs with at least NR_HOLES holes.

     --padding=SIZE_PADDING
	    Show only structs with SIZE_PADDING bytes of padding at its end.

     --padding_ge=SIZE_PADDING
	    Show only structs with at least SIZE_PADDING bytes of padding at its
	    end.

     -I, --show_decl_info
	    Show the file and line number where the tags were defined, if avail-
	    able in the debugging information.

     --skip_encoding_btf_vars
	    By	default, VARs are encoded only for percpu variables. When speci-
	    fied, this option prevents encoding any VARs. Note that this  option
	    can be overridden by the feature "global_var".

     --skip_encoding_btf_decl_tag
	    Do not encode decl tags in BTF.

     --skip_encoding_btf_enum64
	    Do not encode enum64 in BTF.

     --skip_encoding_btf_type_tag
	    Do not encode type tags in BTF.

     --skip_encoding_btf_inconsistent_proto
	    Do not encode functions with multiple inconsistent prototypes or un-
	    expected register use for their parameters, where the registers used
	    do not match calling conventions.

     -j, --jobs=N
	    Run  N  jobs  in parallel. Defaults to number of online processors +
	    10% (like the 'ninja' build system) if no argument is specified.

     -J, --btf_encode
	    Encode BTF information from DWARF, used in the  Linux  kernel  build
	    process when CONFIG_DEBUG_INFO_BTF=y is present, introduced in Linux
	    v5.2.  Used  to implement features such as BPF CO-RE (Compile Once -
	    Run Everywhere).

	    See https://nakryiko.com/posts/bpf-portability-and-co-re/.

     --btf_encode_detached=FILENAME
	    Same thing as -J/--btf_encode, but storing the raw BTF info  into  a
	    separate file.

     --btf_encode_force
	    Ignore those symbols found invalid when encoding BTF.

     --btf_base=PATH
	    Path  to the base BTF file, for instance: vmlinux when encoding ker-
	    nel module BTF information.  This may be inferred when asking for  a
	    /sys/kernel/btf/MODULE, when it will be autoconfigured to "/sys/ker-
	    nel/btf/vmlinux".

     --btf_gen_floats
	    Allow  producing BTF_KIND_FLOAT entries in systems where the vmlinux
	    DWARF information has float types.

     --btf_gen_optimized
	    Generate  BTF  for	functions  with  optimization-related	suffixes
	    (.isra, .constprop).

     --btf_gen_all
	    Allow using all the BTF features supported by pahole.

     --btf_features=FEATURE_LIST
	    Encode  BTF  using	the specified feature list, or specify 'default'
	    for all standard features supported.  This option can be used as  an
	    alternative  to  using  multiple  BTF-related options, and 'default'
	    represents the standard set of BTF features that are in use for ker-
	    nel BTF generation, so is useful as a shortcut for testing the  lat-
	    est  set  of standard features.  However kernel builds will call out
	    specific features rather than using 'default' to ensure that the de-
	    sired features are enabled regardless of pahole version and  associ-
	    ated 'default' set.  Supported standard features are

		 encode_force	    Ignore invalid symbols when encoding BTF; for example
				    if a symbol has an invalid name, it will be ignored
				    and BTF encoding will continue.
		 var		    Encode percpu variables using BTF_KIND_VAR in BTF.
		 float		    Encode floating-point types in BTF.
		 decl_tag	    Encode declaration tags using BTF_KIND_DECL_TAG.
		 type_tag	    Encode type tags using BTF_KIND_TYPE_TAG.
		 enum64 	    Encode enum64 values with BTF_KIND_ENUM64.
		 optimized_func     Encode representations of optimized functions
				    with suffixes like ".isra.0".
		 consistent_func    Avoid encoding inconsistent static functions.
				    These occur when a parameter is optimized out
				    in some CUs and not others, or when the same
				    function name has inconsistent BTF descriptions
				    in different CUs.

	    Supported non-standard features (not enabled for 'default')

		 attributes	    Allow generation of decl_tags and type_tags with
				    kind_flag = 1. These tags can be used to encode
				    arbitrary compiler attributes in BTF, but are
				    backward incompatible.
		 decl_tag_kfuncs    Inject a BTF_KIND_DECL_TAG for each discovered kfunc.
		 distilled_base     For split BTF, generate a distilled version of
				    the associated base BTF to support later relocation
				    of split BTF with a possibly changed base, storing
				    it in a .BTF.base ELF section.
		 global_var	    Encode all global variables using BTF_KIND_VAR in BTF.

	    So	for example, specifying --btf_encode=var,enum64 will result in a
	    BTF encoding that (as well as encoding basic BTF  information)  will
	    contain variables and enum64 values.

	    If	one  wants  to add an extra feature to the set of standard ones,
	    the '+' prefix can be used, i.e.: --btf_features=+reproducible_build
	    will add all default features plus	the  'reproducible_build'  extra
	    feature.

     --btf_features_strict
	    Identical  to  --btf_features  above, but pahole will exit if it en-
	    counters an unrecognized feature.

     --supported_btf_features
	    Show set of BTF features  supported  by  --btf_features  option  and
	    exit.   Useful  for  checking  which  features  are  supported since
	    --btf_features will not emit an error if an unrecognized feature  is
	    specified.

     --running_kernel_vmlinux,
	    Search  for,  possibly  getting  from  a debuginfo server, a vmlinux
	    matching the running kernel build-id (from /sys/kernel/notes).

     -l, --show_first_biggest_size_base_type_member
	    Show first biggest size base_type member.

     -m, --nr_methods
	    Show number of methods of all classes, i.e. the number of  functions
	    have arguments that are pointers to a given class.

	    To get the number of methods for an specific class, please use:

	      $ pahole --nr_methods | grep -w sock
	      sock  1005
	      $

	    In	the  above  example  it  used  the  BTF information in /sys/ker-
	    nel/btf/vmlinux.

     -M, --show_only_data_members
	    Show only the members that use space in the class layout. C++  meth-
	    ods will be suppressed.

     -n, --nr_members
	    Show number of members.

     -N, --class_name_len
	    Show size of classes.

     -O, --dwarf_offset=OFFSET
	    Show tag with DWARF OFFSET.

     -P, --packable
	    Show  only	structs that has holes that can be packed if members are
	    reorganized, for instance when using the --reorganize option.

     -P, --with_flexible_array
	    Show only structs that have a flexible array.

     -P, --with_embedded_flexible_array
	    Show only structs that have an embedded flexible array, i.e. a  con-
	    tained  struct  that  has  flexible arrays, a flexible array "in the
	    middle".

     -q, --quiet
	    Be quieter.

     -s, --sizes
	    Show size of classes.

     -t, --separator=SEP
	    Use SEP as the field separator.

     -T, --nr_definitions
	    Show how many times struct was defined.

     -u, --defined_in
	    Show CUs where CLASS_NAME (-C) is defined.

     --flat_arrays
	    Flatten arrays, so that array[10][2] becomes array[20].  Useful when
	    generating from both CTF/BTF and DWARF encodings for the same binary
	    for testing purposes.

     --suppress_aligned_attribute
	    Suppress forced alignment markers, so that one can	compare  BTF  or
	    CTF output, that don't have that info, to output from DWARF >= 5.

     --suppress_force_paddings

	    Suppress  bitfield forced padding at the end of structs, as this re-
	    quires something like DWARF's DW_AT_alignment, so that one can  com-
	    pare BTF or CTF output, that don't have that info.

     --suppress_packed

	    Suppress the output of the inference of __attribute__((__packed__)),
	    so	that  one can compare BTF or CTF output, the inference algorithm
	    uses things like DW_AT_alignment, so until it is improved  to  infer
	    that as well for BTF, allow disabling this output.

     --fixup_silly_bitfields
	    Converts silly bitfields such as "int foo:32" to plain "int foo".

     -V, --verbose
	    be verbose

     --ptr_table_stats
	    Print  statistics  about ptr_table data structures, used to hold all
	    the types, tags and functions data structures, for development  tun-
	    ing of such tables, tuned for a typical 2021 vmlinux file.

     -w, --word_size=WORD_SIZE
	    Change the arch word size to WORD_SIZE.

     -x, --exclude=PREFIX
	    Exclude PREFIXed classes.

     -X, --cu_exclude=PREFIX
	    Exclude PREFIXed compilation units.

     --lang=languages
	    Only process compilation units built from source code written in the
	    specified languages.

	    Supported languages:

	      ada83,  ada95,  asm,  bliss,  c, c89, c99, c11, c++, c++03, c++11,
	    c++14, cobol74,
	      cobol85, d, dylan,  fortran77,  fortran90,  fortran95,  fortran03,
	    fortran08,
	      go,  haskell,  java, julia, modula2, modula3, objc, objc++, ocaml,
	    opencl,
	      pascal83, pli, python, renderscript, rust, swift, upc

	    The linux kernel, for instance, is written in 'c89' circa 2022,  use
	    that in filters.

	    --lang_exclude=languages  Don't process compilation units built from
	    source code written in the specified languages.

	    To filter out compilation units written in Rust, for instance, use:

	     pahole -j --btf_encode --lang_exclude rust

	    This can also be accomplished by setting  the  environment	variable
	    PAHOLE_LANG_EXCLUDE to the same list of languages, for instance, the
	    following is equivalent to the above:

	     export PAHOLE_LANG_EXCLUDE=rust
	     pahole -j --btf_encode

	    Meaning in both cases 'rust' CUs will be skipped.

	    This  is  useful for scripts where it provides a way to ask for that
	    exclusion for pahole and pfunct, no need to  use  --lang_exclude  in
	    all calls to those tools, just set that environment variable.

     -y, --prefix_filter=PREFIX
	    Include PREFIXed classes.

     -z, --hole_size_ge=HOLE_SIZE
	    Show  only	structs  with  at  least  one  hole  greater or equal to
	    HOLE_SIZE.

     --structs
	    Show only structs, all the other filters apply, i.e.  to  show  just
	    the sizes of all structs combine --structs with --sizes, etc.

     --packed
	    Show  only packed structs, all the other filters apply, i.e. to show
	    just the sizes of all packed structs combine --packed with	--sizes,
	    etc.

     --unions
	    Show only unions, all the other filters apply, i.e. to show just the
	    sizes of all unions combine --union with --sizes, etc.

     --version
	    Show a traditional string version, i.e.: "v1.18".

     --numeric_version
	    Show  a  numeric  only  version,  suitable	for use in Makefiles and
	    scripts where one wants to know what if the  installed  version  has
	    some feature, i.e.: 118 instead of "v1.18".

     --kabi_prefix=STRING
	    When the prefix of the string is STRING, treat the string as STRING.

NOTES
     To enable the generation of debugging information in the Linux kernel build
     process select CONFIG_DEBUG_INFO. This can be done using make menuconfig by
     this  path:  "Kernel Hacking" -> "Compile-time checks and compiler options"
     -> "Compile the kernel with debug info". Consider	as  well  enabling  CON-
     FIG_DEBUG_INFO_BTF  by  going  thru  the aforementioned menuconfig path and
     then selecting "Generate BTF typeinfo". Most modern distributions with eBPF
     support should come with that in all its kernels, greatly facilitating  the
     use of pahole.

     Many  distributions also come with debuginfo packages, so just enable it in
     your package manager repository configuration and install the kernel-debug-
     info, or any other userspace program written in a language  that  the  com-
     piler generates debuginfo (C, C++, for instance).

EXAMPLES
     All  the  examples  here use either /sys/kernel/btf/vmlinux, if present, or
     lookup a vmlinux file matching the running kernel, using the build-id  info
     found in /sys/kernel/notes to make sure it matches.

     Show a type:

     $ pahole -C __u64
     typedef long long unsigned int __u64;
     $

     Works as well if the only argument is a type name:

     $ pahole raw_spinlock_t
     typedef struct raw_spinlock raw_spinlock_t;
     $

     Multiple types can be passed, separated by commas:

     $ pahole raw_spinlock_t,raw_spinlock
     struct raw_spinlock {
	  arch_spinlock_t	     raw_lock;		   /*	  0	4 */

	  /* size: 4, cachelines: 1, members: 1 */
	  /* last cacheline: 4 bytes */
     };
     typedef struct raw_spinlock raw_spinlock_t;
     $

     Types can be expanded:

     $ pahole -E raw_spinlock
     struct raw_spinlock {
	     /* typedef arch_spinlock_t */ struct qspinlock {
		     union {
			     /* typedef atomic_t */ struct {
				     int counter;						   /*	  0	4 */
			     } val;								   /*	  0	4 */
			     struct {
				     /* typedef u8 -> __u8 */ unsigned char locked;		   /*	  0	1 */
				     /* typedef u8 -> __u8 */ unsigned char pending;		   /*	  1	1 */
			     }; 								   /*	  0	2 */
			     struct {
				     /* typedef u16 -> __u16 */ short unsigned int locked_pending; /*	  0	2 */
				     /* typedef u16 -> __u16 */ short unsigned int tail;	   /*	  2	2 */
			     }; 								   /*	  0	4 */
		     }; 									   /*	  0	4 */
	     } raw_lock;									   /*	  0	4 */

	     /* size: 4, cachelines: 1, members: 1 */
	     /* last cacheline: 4 bytes */
     };
     $

     When decoding OOPSes you may want to see the offsets and sizes in hexadeci-
     mal:

     $ pahole --hex thread_struct
     struct thread_struct {
	     struct desc_struct 	tls_array[3];	      /*     0	0x18 */
	     long unsigned int		sp;		      /*  0x18	 0x8 */
	     short unsigned int 	es;		      /*  0x20	 0x2 */
	     short unsigned int 	ds;		      /*  0x22	 0x2 */
	     short unsigned int 	fsindex;	      /*  0x24	 0x2 */
	     short unsigned int 	gsindex;	      /*  0x26	 0x2 */
	     long unsigned int		fsbase; 	      /*  0x28	 0x8 */
	     long unsigned int		gsbase; 	      /*  0x30	 0x8 */
	     struct perf_event *	ptrace_bps[4];	      /*  0x38	0x20 */
	     /* --- cacheline 1 boundary (64 bytes) was 24 bytes ago --- */
	     long unsigned int		debugreg6;	      /*  0x58	 0x8 */
	     long unsigned int		ptrace_dr7;	      /*  0x60	 0x8 */
	     long unsigned int		cr2;		      /*  0x68	 0x8 */
	     long unsigned int		trap_nr;	      /*  0x70	 0x8 */
	     long unsigned int		error_code;	      /*  0x78	 0x8 */
	     /* --- cacheline 2 boundary (128 bytes) --- */
	     struct io_bitmap * 	io_bitmap;	      /*  0x80	 0x8 */
	     long unsigned int		iopl_emul;	      /*  0x88	 0x8 */
	     mm_segment_t		addr_limit;	      /*  0x90	 0x8 */
	     unsigned int		sig_on_uaccess_err:1; /*  0x98: 0 0x4 */
	     unsigned int		uaccess_err:1;	      /*  0x98:0x1 0x4 */

	     /* XXX 30 bits hole, try to pack */
	     /* XXX 36 bytes hole, try to pack */

	     /* --- cacheline 3 boundary (192 bytes) --- */
	     struct fpu 		fpu;		      /*  0xc0 0x1040 */

	     /* size: 4352, cachelines: 68, members: 20 */
	     /* sum members: 4312, holes: 1, sum holes: 36 */
	     /* sum bitfield members: 2 bits, bit holes: 1, sum bit holes: 30 bits */
     };
     $

     OK, I know the offset that causes its a 'struct thread_struct' and that the
     offset  is  0x178,  so  must  be in that 'fpu' struct... No problem, expand
     'struct thread_struct' and combine with grep:

     $ pahole --hex -E thread_struct | egrep '(0x178|struct fpu)' -B4 -A4
	     /* XXX 30 bits hole, try to pack */
	     /* XXX 36 bytes hole, try to pack */

	     /* --- cacheline 3 boundary (192 bytes) --- */
	     struct fpu {
		     unsigned int	last_cpu;					      /*  0xc0	 0x4 */

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

     --
				     /* typedef u8 -> __u8 */ unsigned char alimit;	      /* 0x171	 0x1 */

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

				     struct math_emu_info * info;			      /* 0x178	 0x8 */
				     /* --- cacheline 6 boundary (384 bytes) --- */
				     /* typedef u32 -> __u32 */ unsigned int entry_eip;       /* 0x180	 0x4 */
			     } soft; /* 0x100  0x88 */
			     struct xregs_state {
     $

     Want to know where 'struct thread_struct' is defined in the kernel sources?

     $ pahole -I thread_struct | head -2
     /* Used at: /sys/kernel/btf/vmlinux */
     /* <0> (null):0 */
     $

     Not present in BTF, so use DWARF, takes a little bit longer,  and	assuming
     it finds the matching vmlinux file:

     $ pahole -Fdwarf -I thread_struct | head -2
     /* Used at: /home/acme/git/linux/arch/x86/kernel/head64.c */
     /* <3333> /home/acme/git/linux/arch/x86/include/asm/processor.h:485 */
     $

     To find the biggest data structures in the Linux kernel:

     $ pahole -s | sort -k2 -nr | head -5
     cmp_data		    290904 1
     dec_datas		    274520 1
     cpu_entry_area	    217088 0
     pglist_data	    172928 4
     saved_cmdlines_buffer  131104 1
     $

     The  second  column  is  the  size  in bytes and the third is the number of
     alignment holes in that structure.

     Show data structures that have a raw spinlock and are related  to	the  RCU
     mechanism:

     $ pahole --contains raw_spinlock_t --prefix rcu
     rcu_node
     rcu_data
     rcu_state
     $

     To see that in context, combine it with grep:

     $ pahole rcu_state | grep raw_spinlock_t -B1 -A5
	  /* --- cacheline 52 boundary (3328 bytes) --- */
	  raw_spinlock_t	     ofl_lock;		   /*  3328	4 */

	  /* size: 3392, cachelines: 53, members: 35 */
	  /* sum members: 3250, holes: 7, sum holes: 82 */
	  /* padding: 60 */
     };
     $

PRETTY PRINTING
     pahole can also use the data structure types to pretty print raw data spec-
     ified  via  --prettify.   To consume raw data from the standard input, just
     use '--prettify -'

     It can also pretty print raw data from stdin according to the  type  speci-
     fied:

     $ pahole -C modversion_info drivers/scsi/sg.ko
     struct modversion_info {
	   long unsigned int	      crc;		    /*	   0	 8 */
	   char 		      name[56]; 	    /*	   8	56 */

	   /* size: 64, cachelines: 1, members: 2 */
     };
     $
     $ objcopy -O binary --only-section=__versions drivers/scsi/sg.ko versions
     $
     $ ls -la versions
     -rw-rw-r--. 1 acme acme 7616 Jun 25 11:33 versions
     $
     $ pahole --count 3 -C modversion_info drivers/scsi/sg.ko --prettify versions
     {
	   .crc = 0x8dabd84,
	   .name = "module_layout",
     },
     {
	   .crc = 0x45e4617b,
	   .name = "no_llseek",
     },
     {
	   .crc = 0xa23fae8c,
	   .name = "param_ops_int",
     },
     $
     $ pahole --skip 1 --count 2 -C modversion_info drivers/scsi/sg.ko --prettify - < versions
     {
	   .crc = 0x45e4617b,
	   .name = "no_llseek",
     },
     {
	   .crc = 0xa23fae8c,
	   .name = "param_ops_int",
     },
     $
     This is equivalent to:

     $ pahole --seek_bytes 64 --count 1 -C modversion_info drivers/scsi/sg.ko --prettify versions
     {
	  .crc = 0x45e4617b,
	  .name = "no_llseek",
     },
     $

     -C, --class_name=CLASS_NAME
	    Pretty  print according to this class. Arguments may be passed to it
	    to affect how the pretty printing is performed, e.g.:

	 -C 'perf_event_header(sizeof,type,type_enum=perf_event_type,filter=type==PERF_RECORD_EXIT)'

     This would select the 'struct perf_event_header' as  the  type  to  use  to
     pretty  print records states that the 'size' field in that struct should be
     used to figure out the size of the record (variable  sized  records),  that
     the 'enum perf_event_type' should be used to pretty print the numeric value
     in  perf_event_header->type  and  furthermore  that  it  should  be used to
     heuristically look for structs with the same name (lowercase) of  the  enum
     entry  that  is converted from the type field, using it to pretty print in-
     stead of the base 'perf_event_header' type. See the PRETTY  PRINTING  EXAM-
     PLES section below.

     Furthermore the 'filter=' part can be used, so far with only the '==' oper-
     ator  to  filter  based  on  the  'type'  field  and  converting the string
     'PERF_RECORD_EXIT' to a number according to type_enum.

     The 'sizeof' arg defaults to the 'size' member name, if the name is differ-
     ent, one can use
      'sizeof=sz' form, ditto for 'type=other_member_name' field, that	defaults
     to 'type'.

PRETTY PRINTING EXAMPLES
     Looking  at  the  ELF header for a vmlinux file, using BTF, first lets dis-
     cover the ELF header type:

     $ pahole --sizes | grep -i elf | grep -i _h
     elf64_hdr 64   0
     elf32_hdr 52   0
     $

     Now we can use this to show the first record from offset zero:

     $ pahole -C elf64_hdr --count 1 --prettify /lib/modules/5.8.0-rc3+/build/vmlinux
     {
	  .e_ident = { 127, 69, 76, 70, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	  .e_type = 2,
	  .e_machine = 62,
	  .e_version = 1,
	  .e_entry = 16777216,
	  .e_phoff = 64,
	  .e_shoff = 775923840,
	  .e_flags = 0,
	  .e_ehsize = 64,
	  .e_phentsize = 56,
	  .e_phnum = 5,
	  .e_shentsize = 64,
	  .e_shnum = 80,
	  .e_shstrndx = 79,
     },
     $

     This is equivalent to:

     $ pahole --header elf64_hdr --prettify /lib/modules/5.8.0-rc3+/build/vmlinux

     The --header option also allows reference in other command line options  to
     fields  in  the  header.	This  is  useful when one wants to show multiple
     records in a file and the range where those fields are located is specified
     in header fields, such as for perf.data files:

     $ pahole --hex ~/bin/perf --header perf_file_header --prettify perf.data
     {
	  .magic = 0x32454c4946524550,
	  .size = 0x68,
	  .attr_size = 0x88,
	  .attrs = {
	       .offset = 0xa8,
	       .size = 0x88,
	  },
	  .data = {
	       .offset = 0x130,
	       .size = 0x588,
	  },
	  .event_types = {
	       .offset = 0,
	       .size = 0,
	  },
	  .adds_features = { 0x16717ffc, 0, 0, 0 },
     },
     $

     So to display the cgroups records in the perf_file_header.data  section  we
     can use:

     $ pahole ~/bin/perf --header=perf_file_header --seek_bytes '$header.data.offset' --size_bytes='$header.data.size' -C 'perf_event_header(sizeof,type,type_enum=perf_event_type,filter=type==PERF_RECORD_CGROUP)' --prettify perf.data
     {
	  .header = {
	       .type = PERF_RECORD_CGROUP,
	       .misc = 0,
	       .size = 40,
	  },
	  .id = 1,
	  .path = "/",
     },
     {
	  .header = {
	       .type = PERF_RECORD_CGROUP,
	       .misc = 0,
	       .size = 48,
	  },
	  .id = 1553,
	  .path = "/system.slice",
     },
     {
	  .header = {
	       .type = PERF_RECORD_CGROUP,
	       .misc = 0,
	       .size = 48,
	  },
	  .id = 8,
	  .path = "/machine.slice",
     },
     {
	  .header = {
	       .type = PERF_RECORD_CGROUP,
	       .misc = 0,
	       .size = 128,
	  },
	  .id = 7828,
	  .path = "/machine.slice/libpod-42be8e8d4eb9d22405845005f0d04ea398548dccc934a150fbaa3c1f1f9492c2.scope",
     },
     {
	  .header = {
	       .type = PERF_RECORD_CGROUP,
	       .misc = 0,
	       .size = 88,
	  },
	  .id = 13,
	  .path = "/machine.slice/machine-qemu\x2d1\x2drhel6.sandy.scope",
     },
     $

     For the common case of the header having a member that has the 'offset' and
     'size' members, it is possible to use this more compact form:

     $ pahole ~/bin/perf --header=perf_file_header --range=data -C 'perf_event_header(sizeof,type,type_enum=perf_event_type,filter=type==PERF_RECORD_CGROUP)' --prettify perf.data

     This  uses  ~/bin/perf  to  get  the  type definitions, the defines 'struct
     perf_file_header' as the header,  then  seeks  '$header.data.offset'  bytes
     from  the	start of the file, and considers '$header.data.size' bytes worth
     of such records. The filter expression may omit a common  prefix,	in  this
     case   it	 could	additionally  be  equivalently	written  as  both  'fil-
     ter=type==CGROUP' or the 'filter=' can also be omitted, getting as  compact
     as 'type==CGROUP':

     If we look at:

     $ pahole ~/bin/perf -C perf_event_header
     struct perf_event_header {
	  __u32 		     type;		   /*	  0	4 */
	  __u16 		     misc;		   /*	  4	2 */
	  __u16 		     size;		   /*	  6	2 */

	  /* size: 8, cachelines: 1, members: 3 */
	  /* last cacheline: 8 bytes */
     };
     $

     And:

     $ pahole ~/bin/perf -C perf_event_type
     enum perf_event_type {
	  PERF_RECORD_MMAP = 1,
	  PERF_RECORD_LOST = 2,
	  PERF_RECORD_COMM = 3,
	  PERF_RECORD_EXIT = 4,
	  PERF_RECORD_THROTTLE = 5,
	  PERF_RECORD_UNTHROTTLE = 6,
	  PERF_RECORD_FORK = 7,
	  PERF_RECORD_READ = 8,
	  PERF_RECORD_SAMPLE = 9,
	  PERF_RECORD_MMAP2 = 10,
	  PERF_RECORD_AUX = 11,
	  PERF_RECORD_ITRACE_START = 12,
	  PERF_RECORD_LOST_SAMPLES = 13,
	  PERF_RECORD_SWITCH = 14,
	  PERF_RECORD_SWITCH_CPU_WIDE = 15,
	  PERF_RECORD_NAMESPACES = 16,
	  PERF_RECORD_KSYMBOL = 17,
	  PERF_RECORD_BPF_EVENT = 18,
	  PERF_RECORD_CGROUP = 19,
	  PERF_RECORD_TEXT_POKE = 20,
	  PERF_RECORD_MAX = 21,
     };
     $

     And furthermore:

     $ pahole ~/bin/perf -C perf_record_cgroup
     struct perf_record_cgroup {
	  struct perf_event_header   header;		   /*	  0	8 */
	  __u64 		     id;		   /*	  8	8 */
	  char			     path[4096];	   /*	 16  4096 */

	  /* size: 4112, cachelines: 65, members: 3 */
	  /* last cacheline: 16 bytes */
     };
     $

     Then  we  can  see how the perf_event_header.type could be converted from a
     __u32   to   a   string   (PERF_RECORD_CGROUP).	If   we   remove    that
     type_enum=perf_event_type,   we   will   lose  the  conversion  of  'struct
     perf_event_header' to the more descriptive 'struct perf_record_cgroup', and
     also the beautification of the header.type field:

     $ pahole ~/bin/perf --header=perf_file_header --seek_bytes '$header.data.offset' --size_bytes='$header.data.size' -C 'perf_event_header(sizeof,type,filter=type==19)' --prettify perf.data
     {
	  .type = 19,
	  .misc = 0,
	  .size = 40,
     },
     {
	  .type = 19,
	  .misc = 0,
	  .size = 48,
     },
     {
	  .type = 19,
	  .misc = 0,
	  .size = 48,
     },
     {
	  .type = 19,
	  .misc = 0,
	  .size = 128,
     },
     {
	  .type = 19,
	  .misc = 0,
	  .size = 88,
     },
     $

     Some of the records are not found in 'type_enum=perf_event_type' so some of
     the records don't get converted to a type that fully  shows  its  contents.
     For   perf   we   know   that  those  are	in  another  enumeration,  'enum
     perf_user_event_type', so, for these cases, we can create a 'virtual enum',
     i.e. the sum of two enums and then get all those entries decoded and  prop-
     erly casted, first few records with just 'enum perf_event_type':

     $ pahole ~/bin/perf --header=perf_file_header --seek_bytes '$header.data.offset' --size_bytes='$header.data.size' -C 'perf_event_header(sizeof,type,type_enum=perf_event_type)' --count 4 --prettify perf.data
     {
	  .type = 79,
	  .misc = 0,
	  .size = 32,
     },
     {
	  .type = 73,
	  .misc = 0,
	  .size = 40,
     },
     {
	  .type = 74,
	  .misc = 0,
	  .size = 32,
     },
     {
	  .header = {
	       .type = PERF_RECORD_CGROUP,
	       .misc = 0,
	       .size = 40,
	  },
	  .id = 1,
	  .path = "/",
     },
     $

     Now	 with	      both	   enumerations,	i.e.	    with
     'type_enum=perf_event_type+perf_user_event_type':

     $ pahole ~/bin/perf --header=perf_file_header --seek_bytes '$header.data.offset' --size_bytes='$header.data.size' -C 'perf_event_header(sizeof,type,type_enum=perf_event_type+perf_user_event_type)' --count 5 --prettify perf.data
     {
	  .header = {
	       .type = PERF_RECORD_TIME_CONV,
	       .misc = 0,
	       .size = 32,
	  },
	  .time_shift = 31,
	  .time_mult = 1016803377,
	  .time_zero = 435759009518382,
     },
     {
	  .header = {
	       .type = PERF_RECORD_THREAD_MAP,
	       .misc = 0,
	       .size = 40,
	  },
	  .nr = 1,
	  .entries = 0x50 0x7e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00,
     },
     {
	  .header = {
	       .type = PERF_RECORD_CPU_MAP,
	       .misc = 0,
	       .size = 32,
	  },
	  .data = {
	       .type = 1,
	       .data = "",
	  },
     },
     {
	  .header = {
	       .type = PERF_RECORD_CGROUP,
	       .misc = 0,
	       .size = 40,
	  },
	  .id = 1,
	  .path = "/",
     },
     {
	  .header = {
	       .type = PERF_RECORD_CGROUP,
	       .misc = 0,
	       .size = 48,
	  },
	  .id = 1553,
	  .path = "/system.slice",
     },
     $

     It is possible to pass multiple types, one has only to make sure  they  ap-
     pear  in  the  file  in  sequence,  i.e. for the perf.data example, see the
     perf_file_header dump above, one can print the  perf_file_attr  structs  in
     the  header  attrs range, then the perf_event_header in the data range with
     the following command:

     pahole ~/bin/perf --header=perf_file_header	  -C 'perf_file_attr(range=attrs),perf_event_header(range=data,sizeof,type,type_enum=perf_event_type+perf_user_event_type)' --prettify perf.data

SEE ALSO
     eu-readelf(1), readelf(1), objdump(1).

     https://www.kernel.org/doc/ols/2007/ols2007v2-pages-35-44.pdf.

AUTHOR
     pahole was written and is maintained by Arnaldo Carvalho de Melo <acme@ker-
     nel.org>.

     Thanks to Andrii Nakryiko and Martin KaFai Lau for providing  the	BTF  en-
     coder and improving the codebase while making sure the BTF encoder works as
     needed  to be used in encoding the Linux kernel .BTF section from the DWARF
     info generated by gcc. For that Andrii wrote a BTF deduplicator  in  libbpf
     that is used by pahole.

     Also  thanks  to Conectiva, Mandriva and Red Hat for allowing me to work on
     these tools.

     Please send bug reports to <dwarves@vger.kernel.org>.

     No subscription is required.

dwarves 			January 16, 2020		       pahole(1)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=pahole&sektion=1&manpath=FreeBSD+Ports+15.1.quarterly>

home | help