Commit Graph

1526 Commits

Author SHA1 Message Date
Arnaldo Carvalho de Melo dd15aa4b0a dwarves: Prep v1.19
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-23 09:52:44 -03:00
Arnaldo Carvalho de Melo bf21da4075 fprintf: Make typedef__fprintf print anonymous enums
In all the examples the kernel BTF info is being used (/sys/kernel/btf/vmlinux).

Before:

  $ pahole ZSTD_strategy
  typedef enum  ZSTD_strategy;
  $

After:

  $ pahole ZSTD_strategy
  typedef enum {
  	ZSTD_fast    = 0,
  	ZSTD_dfast   = 1,
  	ZSTD_greedy  = 2,
  	ZSTD_lazy    = 3,
  	ZSTD_lazy2   = 4,
  	ZSTD_btlazy2 = 5,
  	ZSTD_btopt   = 6,
  	ZSTD_btopt2  = 7,
  } ZSTD_strategy;
  $

Named ones continue to work as before:

  $ pahole timespec_type
  enum timespec_type {
  	TT_NONE   = 0,
  	TT_NATIVE = 1,
  	TT_COMPAT = 2,
  };
  $

And the ones inside structs, when expanded, as well:

  $ pahole ZSTD_parameters
  typedef struct {
  	ZSTD_compressionParameters cParams;              /*     0    28 */
  	ZSTD_frameParameters       fParams;              /*    28    12 */

  	/* size: 40, cachelines: 1, members: 2 */
  	/* last cacheline: 40 bytes */
  } ZSTD_parameters;
  $ pahole -E ZSTD_parameters
  typedef struct {
  	/* typedef ZSTD_compressionParameters */ struct {
  		unsigned int       windowLog;                                            /*     0     4 */
  		unsigned int       chainLog;                                             /*     4     4 */
  		unsigned int       hashLog;                                              /*     8     4 */
  		unsigned int       searchLog;                                            /*    12     4 */
  		unsigned int       searchLength;                                         /*    16     4 */
  		unsigned int       targetLength;                                         /*    20     4 */
  		/* typedef ZSTD_strategy */ enum {
  			ZSTD_fast    = 0,
  			ZSTD_dfast   = 1,
  			ZSTD_greedy  = 2,
  			ZSTD_lazy    = 3,
  			ZSTD_lazy2   = 4,
  			ZSTD_btlazy2 = 5,
  			ZSTD_btopt   = 6,
  			ZSTD_btopt2  = 7,
  		} strategy; /*    24     4 */
  	} cParams; /*     0    28 */
  	/* typedef ZSTD_frameParameters */ struct {
  		unsigned int       contentSizeFlag;                                      /*    28     4 */
  		unsigned int       checksumFlag;                                         /*    32     4 */
  		unsigned int       noDictIDFlag;                                         /*    36     4 */
  	} fParams; /*    28    12 */

  	/* size: 40, cachelines: 1, members: 2 */
  	/* last cacheline: 40 bytes */
  } ZSTD_parameters;
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-19 11:41:18 -03:00
Arnaldo Carvalho de Melo 9c4bdf9331 fprintf: Align enumerators
$ pahole timespec_type
  enum timespec_type {
  	TT_NONE   = 0,
  	TT_NATIVE = 1,
  	TT_COMPAT = 2,
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-19 11:36:20 -03:00
Arnaldo Carvalho de Melo 89cf28228a fprintf: Add enumeration__max_entry_name_len()
Cache the results, will be used when pretty printing enumerations, to
align the entries.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-19 11:25:47 -03:00
Arnaldo Carvalho de Melo 932b84eb45 fprintf: Make typedef__fprintf print anonymous structs
For instance, the Dwarf_Op typedef was found but since it is an
anonymous struct we get:

  $ pahole -C Dwarf_Op build/pahole
  typedef struct  Dwarf_Op;
  $

Which is not useful, fix it:

  $ pahole -C Dwarf_Op build/pahole
  typedef struct {
  	uint8_t                    atom;                 /*     0     1 */

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

  	Dwarf_Word                 number;               /*     8     8 */
  	Dwarf_Word                 number2;              /*    16     8 */
  	Dwarf_Word                 offset;               /*    24     8 */

  	/* size: 32, cachelines: 1, members: 4 */
  	/* sum members: 25, holes: 1, sum holes: 7 */
  	/* last cacheline: 32 bytes */
  } Dwarf_Op;
  $

Reported-by: Matthias Schwarzott <zzam@gentoo.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-19 10:32:00 -03:00
Arnaldo Carvalho de Melo 4a1479305b pahole: Add heuristic to auto-add --btf_base for /sys/kernel/btf/ prefixed files
Before:

  $ pahole /sys/kernel/btf/wmi -C wmi_block
  libbpf: Invalid BTF string section
  pahole: /sys/kernel/btf/wmi: No such device
  $

After:

  $ pahole /sys/kernel/btf/wmi -C wmi_block
  struct wmi_block {
  	struct wmi_device          dev;                  /*     0   760 */

  	/* XXX last struct has 7 bytes of padding */

  	/* --- cacheline 11 boundary (704 bytes) was 56 bytes ago --- */
  	struct list_head           list;                 /*   760    16 */
  	/* --- cacheline 12 boundary (768 bytes) was 8 bytes ago --- */
  	struct guid_block          gblock;               /*   776    20 */

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

  	struct miscdevice          char_dev;             /*   800    80 */

  	/* XXX last struct has 6 bytes of padding */

  	/* --- cacheline 13 boundary (832 bytes) was 48 bytes ago --- */
  	struct mutex               char_mutex;           /*   880    32 */
  	/* --- cacheline 14 boundary (896 bytes) was 16 bytes ago --- */
  	struct acpi_device *       acpi_device;          /*   912     8 */
  	wmi_notify_handler         handler;              /*   920     8 */
  	void *                     handler_data;         /*   928     8 */
  	u64                        req_buf_size;         /*   936     8 */
  	bool                       read_takes_no_args;   /*   944     1 */

  	/* size: 952, cachelines: 15, members: 10 */
  	/* sum members: 941, holes: 1, sum holes: 4 */
  	/* padding: 7 */
  	/* paddings: 2, sum paddings: 13 */
  	/* last cacheline: 56 bytes */
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-18 11:10:23 -03:00
Arnaldo Carvalho de Melo e1d0104582 btf: Fallback to raw BTF mode if the header magic matches
We had this heuristic to try raw BTF if the file starts with
/sys/kernel/btf/, but if we are in that directory already then we
continue trying it as an ELF file, fix it:

Before:

  $ cd /sys/kernel/btf/
  $ pahole -C list_head vmlinux
  pahole: vmlinux: No such device
  $

After:

  $ pahole -C list_head vmlinux
  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 */
  };
  $

Works as well for modules:

  $ pahole -C wmi_device vmlinux
  pahole: type 'wmi_device' not found
  $ pahole -C wmi_device --btf_base vmlinux wmi
  struct wmi_device {
  	struct device              dev;                  /*     0   752 */

  	/* XXX last struct has 7 bytes of padding */

  	/* --- cacheline 11 boundary (704 bytes) was 48 bytes ago --- */
  	bool                       setable;              /*   752     1 */

  	/* size: 760, cachelines: 12, members: 2 */
  	/* padding: 7 */
  	/* paddings: 1, sum paddings: 7 */
  	/* last cacheline: 56 bytes */
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-18 10:34:43 -03:00
Arnaldo Carvalho de Melo 24cea890ab pahole: Force '-F btf' with --btf_base
If a .ko file has both DWARF and BTF, we were needing to use '-F btf' to
make the BTF info to be used, to make command lines more concise imply
'-F btf' if --btf_base is used.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-18 10:34:39 -03:00
Arnaldo Carvalho de Melo cfad738682 libbtf: Assume its raw_btf if filename starts with "/sys/kernel/btf/"
Previously we used this just for vmlinux, now that we have kernel
modules, use it for those as well.

Now this works:

  $ pahole wmi_block
  pahole: type 'wmi_block' not found
  $ pahole --btf_base /sys/kernel/btf/vmlinux /sys/kernel/btf/wmi -C wmi_block
  struct wmi_block {
  	struct wmi_device          dev;                  /*     0   760 */

  	/* XXX last struct has 7 bytes of padding */

  	/* --- cacheline 11 boundary (704 bytes) was 56 bytes ago --- */
  	struct list_head           list;                 /*   760    16 */
  	/* --- cacheline 12 boundary (768 bytes) was 8 bytes ago --- */
  	struct guid_block          gblock;               /*   776    20 */

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

  	struct miscdevice          char_dev;             /*   800    80 */

  	/* XXX last struct has 6 bytes of padding */

  	/* --- cacheline 13 boundary (832 bytes) was 48 bytes ago --- */
  	struct mutex               char_mutex;           /*   880    32 */
  	/* --- cacheline 14 boundary (896 bytes) was 16 bytes ago --- */
  	struct acpi_device *       acpi_device;          /*   912     8 */
  	wmi_notify_handler         handler;              /*   920     8 */
  	void *                     handler_data;         /*   928     8 */
  	u64                        req_buf_size;         /*   936     8 */
  	bool                       read_takes_no_args;   /*   944     1 */

  	/* size: 952, cachelines: 15, members: 10 */
  	/* sum members: 941, holes: 1, sum holes: 4 */
  	/* padding: 7 */
  	/* paddings: 2, sum paddings: 13 */
  	/* last cacheline: 56 bytes */
  };
  $

I.e. it assumes /sys/kernel/btf/wmi is raw BTF, and finds in it a type
'struct wmi_block' that is not present in /sys/kernel/btf/vmlinux, i.e.
its a module specific type, that uses types that are in
/sys/kernel/btf/vmlinux, such as 'struct list_head'.

For reference, here are the sizes of those files:

  $ ls -la /sys/kernel/btf/vmlinux /sys/kernel/btf/wmi
  -r--r--r--. 1 root root 4241472 Nov 17 20:14 /sys/kernel/btf/vmlinux
  -r--r--r--. 1 root root    2866 Nov 17 20:14 /sys/kernel/btf/wmi
  $

It is also possible to use the .ko file:

  $ uname -r
  5.10.0-rc3.bpfsign+
  $ pahole wmi_notify_handler
  pahole: type 'wmi_notify_handler' not found
  $ pahole -F btf --btf_base /sys/kernel/btf/vmlinux /lib/modules/5.10.0-rc3.bpfsign+/kernel/drivers/platform/x86/wmi.ko -C wmi_notify_handler
  typedef void (*wmi_notify_handler)(u32, void *);
  $ pahole -F btf --btf_base /sys/kernel/btf/vmlinux /lib/modules/5.10.0-rc3.bpfsign+/kernel/drivers/platform/x86/wmi.ko -C wmi_device
  struct wmi_device {
  	struct device              dev;                  /*     0   752 */

  	/* XXX last struct has 7 bytes of padding */

  	/* --- cacheline 11 boundary (704 bytes) was 48 bytes ago --- */
  	bool                       setable;              /*   752     1 */

  	/* size: 760, cachelines: 12, members: 2 */
  	/* padding: 7 */
  	/* paddings: 1, sum paddings: 7 */
  	/* last cacheline: 56 bytes */
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-18 09:32:56 -03:00
Arnaldo Carvalho de Melo 7293c7fcea pahole: The --btf_base option receives a PATH, not a SIZE
Fixup copy'n'paste error.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-18 09:21:31 -03:00
Jiri Olsa b3dd4f3c3d btf_encoder: Use better fallback message
Using more suitable fallback message for the case when the ftrace filter
can't be used because of missing symbols.

Committer notes:

Before:

  vmlinux not detected, falling back to dwarf data

Now:

  ftrace symbols not detected, falling back to DWARF data

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Requested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Hao Luo <haoluo@google.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-17 14:55:46 -03:00
Jiri Olsa d06048c530 btf_encoder: Move btf_elf__verbose/btf_elf__force setup
With introduction of collect_symbols function, we moved the percpu
variables code before btf_elf__verbose/btf_elf__force setup, so they
don't have any effect in that code anymore.

Also btf_elf__verbose is used in code that prepares ftrace filter for
functions generations, also called within collect_symbols function.

Moving btf_elf__verbose/btf_elf__force setup early in the cu__encode_btf
function, so we can get verbose messages and see the effect of the force
option.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Hao Luo <haoluo@google.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-16 16:45:40 -03:00
Jiri Olsa 8156bec8ae btf_encoder: Fix function generation
Current conditions for picking up function records break BTF data on
some gcc versions.

Some function records can appear with no arguments but with declaration
tag set, so moving the 'fn->declaration' in front of other checks.

Then checking if argument names are present and finally checking ftrace
filter if it's present. If ftrace filter is not available, using the
external tag to filter out non external functions.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Hao Luo <haoluo@google.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-16 09:02:34 -03:00
Jiri Olsa d0cd007339 btf_encoder: Generate also .init functions
Currently we skip functions under .init* sections, Removing the .init*
section check, BTF now contains also functions from .init* sections.

Andrii's explanation from email:

> ...                  I think we should just drop the __init check and
> include all the __init functions into BTF. There could be cases where
> we'd need to attach BPF programs to __init functions (e.g., bpf_lsm
> security cases), so having BTFs for those FUNCs are necessary as well.
> Ftrace currently disallows that, but it's only because no user-space
> application has a way to attach probes early enough. This might change
> in the future, so there is no need to invent special mechanisms now
> for bpf_iter function preservation. Let's just include all __init
> functions in BTF.

It's over ~2000 functions on my .config:

   $ bpftool btf dump file ./vmlinux | grep 'FUNC ' | wc -l
   41505
   $ bpftool btf dump file /sys/kernel/btf/vmlinux | grep 'FUNC ' | wc -l
   39256

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Hao Luo <haoluo@google.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-16 09:02:21 -03:00
Arnaldo Carvalho de Melo 25753e0396 pfunct: Use load stealer to speed up --class
We were loading everything to then iterate looking for functions with
pointers to the --class argument, do it in the stealer and go on
ditching the already processed data, greatly speeding up the process.

  $ pfunct -c perf_event_attr
  security_perf_event_open
  register_user_hw_breakpoint
  modify_user_hw_breakpoint
  perf_event_create_kernel_counter
  register_wide_hw_breakpoint
  bpf_lsm_perf_event_open
  modify_user_hw_breakpoint_check
  perf_event_create_kernel_counter
  $
  $
  $ pfunct bpf_lsm_perf_event_open
  int bpf_lsm_perf_event_open(struct perf_event_attr * attr, int type);
  $

  $ for function in `pfunct -c perf_event_attr` ; do pfunct $function ; done
  int security_perf_event_open(struct perf_event_attr * attr, int type);
  struct perf_event * register_user_hw_breakpoint(struct perf_event_attr * attr, perf_overflow_handler_t triggered, void * context, struct task_struct * tsk);
  int modify_user_hw_breakpoint(struct perf_event * bp, struct perf_event_attr * attr);
  struct perf_event * perf_event_create_kernel_counter(struct perf_event_attr * attr, int cpu, struct task_struct * task, perf_overflow_handler_t callback, void * context);
  struct perf_event * * register_wide_hw_breakpoint(struct perf_event_attr * attr, perf_overflow_handler_t triggered, void * context);
  int bpf_lsm_perf_event_open(struct perf_event_attr * attr, int type);
  int modify_user_hw_breakpoint_check(struct perf_event * bp, struct perf_event_attr * attr, bool check);
  struct perf_event * perf_event_create_kernel_counter(struct perf_event_attr * attr, int cpu, struct task_struct * task, perf_overflow_handler_t callback, void * context);
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-16 08:15:23 -03:00
Arnaldo Carvalho de Melo aa8fb8c091 man-pages: Add entry for -J/--btf_encode to pahole's man page
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-13 08:36:32 -03:00
Andrii Nakryiko ace05ba941 btf: Add support for split BTF loading and encoding
Add support for generating split BTF, in which there is a designated base
BTF, containing a base set of types, and a split BTF, which extends main BTF
with extra types, that can reference types and strings from the main BTF.

This is going to be used to generate compact BTFs for kernel modules, with
vmlinux BTF being a main BTF, which all kernel modules are based off of.

These changes rely on patch set [0] to be present in libbpf submodule.

  [0] https://patchwork.kernel.org/project/netdevbpf/list/?series=377859&state=*

Committer notes:

Fixed up wrt ARGP_numeric_version and added a man page entry.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-11 09:12:44 -03:00
Andrii Nakryiko 7290d08b4a libbpf: Update libbpf submodule reference to latest master
Pull in latest libbpf changes, containing split BTF APIs.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-11 08:43:44 -03:00
Andrii Nakryiko 344f2483cf libbtf: Improve variable naming and error reporting when writing out BTF
Rename a few local variables to reflects the purpose a bit better. Also
separate writing out BTF raw data and objcopy invocation into two
separate steps and improve error reporting for each.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-11 08:43:40 -03:00
Andrii Nakryiko 94a7535939 btf_encoder: Fix array index type numbering
Take into account type ID offset, accumulated from previous CUs, when
calculating a new type ID for the generated array index type.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-11 08:23:40 -03:00
Arnaldo Carvalho de Melo 9fa3a100f7 pfunct: Use a load stealer to stop as soon as a function is found
When --function/-f or just using the function name as the sole arg,
greatly speeding up the process.

Example using /sys/kernel/btf/vmlinux:

Before:

  $ perf stat -r5 pfunct tcp_v4_rcv
  int tcp_v4_rcv(struct sk_buff * skb);
  int tcp_v4_rcv(struct sk_buff * skb);
  int tcp_v4_rcv(struct sk_buff * skb);
  int tcp_v4_rcv(struct sk_buff * skb);
  int tcp_v4_rcv(struct sk_buff * skb);

   Performance counter stats for 'pfunct tcp_v4_rcv' (5 runs):

           13,199.77 msec task-clock:u              #    1.000 CPUs utilized            ( +-  0.27% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
               9,426      page-faults:u             #    0.714 K/sec                    ( +-  0.02% )
      57,793,399,298      cycles:u                  #    4.378 GHz                      ( +-  0.29% )  (83.33%)
         305,498,117      stalled-cycles-frontend:u #    0.53% frontend cycles idle     ( +-  2.87% )  (83.33%)
      15,537,903,799      stalled-cycles-backend:u  #   26.89% backend cycles idle      ( +-  4.04% )  (83.33%)
     126,344,414,608      instructions:u            #    2.19  insn per cycle
                                                    #    0.12  stalled cycles per insn  ( +-  0.00% )  (83.33%)
      26,880,839,847      branches:u                # 2036.463 M/sec                    ( +-  0.01% )  (83.34%)
         122,011,679      branch-misses:u           #    0.45% of all branches          ( +-  0.13% )  (83.33%)

             13.2005 +- 0.0355 seconds time elapsed  ( +-  0.27% )

  $

After:

  $ perf stat -r5 pfunct tcp_v4_rcv
  int tcp_v4_rcv(struct sk_buff * skb);
  int tcp_v4_rcv(struct sk_buff * skb);
  int tcp_v4_rcv(struct sk_buff * skb);
  int tcp_v4_rcv(struct sk_buff * skb);
  int tcp_v4_rcv(struct sk_buff * skb);

   Performance counter stats for 'pfunct tcp_v4_rcv' (5 runs):

               41.89 msec task-clock:u              #    0.993 CPUs utilized            ( +- 11.34% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
               9,424      page-faults:u             #    0.225 M/sec                    ( +-  0.01% )
         117,923,321      cycles:u                  #    2.815 GHz                      ( +-  2.13% )  (82.15%)
           1,014,685      stalled-cycles-frontend:u #    0.86% frontend cycles idle     ( +-  5.81% )  (83.48%)
          37,728,636      stalled-cycles-backend:u  #   31.99% backend cycles idle      ( +-  4.77% )  (83.80%)
         215,262,313      instructions:u            #    1.83  insn per cycle
                                                    #    0.18  stalled cycles per insn  ( +-  0.96% )  (83.77%)
          36,786,262      branches:u                #  878.162 M/sec                    ( +-  0.46% )  (83.80%)
             338,322      branch-misses:u           #    0.92% of all branches          ( +-  2.10% )  (83.01%)

             0.04220 +- 0.00478 seconds time elapsed  ( +- 11.33% )

  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-10 15:47:17 -03:00
Arnaldo Carvalho de Melo de18bd5fe3 pfunct: Try sole argument as a function name, just like pahole
I.e.:

This:

  $ pfunct -f tcp_v4_rcv
  int tcp_v4_rcv(struct sk_buff * skb);
  $

Now is equivalent to:

  $ pfunct tcp_v4_rcv
  int tcp_v4_rcv(struct sk_buff * skb);
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-10 14:57:35 -03:00
Arnaldo Carvalho de Melo bc1afd4585 pahole: Introduce --numeric_version for use in scripts and Makefiles
In Makefiles we want to do purely numeric comparisions, such as in the
Linux kernel Makefiles and scripts, that have things like this at the
moment:

  $ grep PAHOLE */*.sh
  scripts/link-vmlinux.sh:	if ! [ -x "$(command -v ${PAHOLE})" ]; then
  scripts/link-vmlinux.sh:		echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available"
  scripts/link-vmlinux.sh:	pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/')
  scripts/link-vmlinux.sh:		echo >&2 "BTF: ${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.16"
  scripts/link-vmlinux.sh:	LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}
  $

So just provide:

  $ pahole --numeric_version
  118
  $

While keeping the --version output for older Makefiles and scripts.

Cc: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-10 13:04:22 -03:00
Arnaldo Carvalho de Melo 784c3dfbd6 dwarves: Switch from a string based version to major/minor numbers
Nothing changes now, this continues to work just the same:

  $ pahole --version
  v1.18
  $ pfunct --version
  v1.18
  $

This just paves the way for us to have a '--numeric-version' that will
do away with the dot and the leading 'v' and that can be used in
Makefiles to check if the required minimum version is available, to
avoid what we have now in the Linux kernel:

  config PAHOLE_HAS_SPLIT_BTF
         def_bool $(success, test `$(PAHOLE) --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/'` -ge "119")

With the next cset we'll be able to do just:

	 test `$(PAHOLE) --numeric-version` -ge "119"

Cc: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-10 12:41:42 -03:00
Arnaldo Carvalho de Melo fc06ee1b6e pahole: Check if the sole arg is a file, not considering it a type if so
Before we would have:

  $ gcc x.c -Wall -ggdb3
  $ strip -s a.out
  $ pahole ./a.out
  $

I.e. no types, no output.

Then when we started trying out the sole arg as a type to lookup either
on a vmlinux found via its build id in /sys/kernel/notes or
/sys/kernel/btf/vmlinux we instead showed this for a binary without type
info:

  $ pahole ./a.out
  pahole: type './a.out' not found
  $

Now we show:

  $ pahole a.out
  pahole: file 'a.out' has no supported type information.
  $

Reported-by: Jan Engelhardt <jengelh@inai.de>
Bugtracker: https://github.com/acmel/dwarves/issues/14
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-10 12:26:11 -03:00
Arnaldo Carvalho de Melo f47b3a2df3 dwarf_loader: Fix partial unit warning
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-09 15:45:26 -03:00
Jiri Olsa 5a22c2de79 btf_encoder: Change functions check due to broken dwarf
We need to generate just single BTF instance for the function, while
DWARF data contains multiple instances of DW_TAG_subprogram tag.

Unfortunately we can no longer rely on DW_AT_declaration tag
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97060)

Instead we apply following checks:

  - argument names are defined for the function

  - there's symbol and address defined for the function

  - function is generated only once

Also because we want to follow kernel's ftrace traceable functions, this
patchset is adding extra check that the function is one of the ftrace's
functions.

All ftrace functions addresses are stored in vmlinux binary within
symbols:

  __start_mcount_loc
  __stop_mcount_loc

During object preparation code we read those addresses, sort them and
use them as filter for all detected dwarf functions.

We also filter out functions within .init section, ftrace is doing that
in runtime. At the same time we keep functions from
.init.bpf.preserve_type, because they are needed in BTF.

I can still see several differences to ftrace functions in
/sys/kernel/debug/tracing/available_filter_functions file:

  - available_filter_functions includes modules

  - available_filter_functions includes functions like:
      __acpi_match_device.part.0.constprop.0
      acpi_ns_check_sorted_list.constprop.0
      acpi_os_unmap_generic_address.part.0
      acpiphp_check_bridge.part.0

    which are not part of dwarf data

  - BTF includes multiple functions like:

      __clk_register_clkdev
      clk_register_clkdev

    which share same code so they appear just as single function
    in available_filter_functions, but dwarf keeps track of both
    of them

  - BTF includes iterator functions, which do not make it to
    available_filter_functions

With this change I'm getting 38384 BTF functions, which when added above
functions to consideration gives same amount of functions in
available_filter_functions.

The patch still keeps the original function filter condition (that uses
current fn->declaration check) in case the object does not contain
*_mcount_loc symbol -> object is not vmlinux.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Hao Luo <haoluo@google.com>
Cc: Mark Wieelard <mjw@redhat.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-09 14:27:11 -03:00
Jiri Olsa 7b1af3f484 btf_encoder: Move find_all_percpu_vars in generic collect_symbols
Move find_all_percpu_vars() under generic collect_symbols() that walks
over symbols and calls collect_percpu_var().

We will add another collect function that needs to go through all the
symbols, so it's better we go through them just once.

There's no functional change intended.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Hao Luo <haoluo@google.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Mark Wieelard <mjw@redhat.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-09 14:25:49 -03:00
Hao Luo 863e6f0f2c btf_encoder: Check var type after checking var addr.
Commit 2e719cca66 ("btf_encoder: revamp how per-CPU variables are
encoded") adds percpu_var_exists() to filter out the symbols that are
not percpu var. However, the check comes after checking the var's type.
There can be symbols that are of zero type. If we hit that, btf_encoder
will not work without '--btf_encode_force'.  So we should check
percpu_var_exists before checking var's type.

Tested:

  haoluo@haoluo:~/kernel/tip$ gcc --version
  gcc (GCC) 10.2.0
  Copyright (C) 2020 Free Software Foundation, Inc.
  This is free software; see the source for copying conditions.  There is NO
  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Before:

  haoluo@haoluo:~/kernel/tip$ make clean -s
  haoluo@haoluo:~/kernel/tip$ make -j 32 -s
    LINK     resolve_btfids
  error: found variable in CU 'kernel/bpf/btf.c' that has void type
  Encountered error while encoding BTF.
  FAILED: load BTF from vmlinux: Unknown error -2make: *** [Makefile:1164: vmlinux] Error 255

After:

  haoluo@haoluo:~/kernel/tip$ make clean -s
  haoluo@haoluo:~/kernel/tip$ make -j 32 -s
    LINK     resolve_btfids
  haoluo@haoluo:~/kernel/tip$

Fixes: 2e719cc ("btf_encoder: revamp how per-CPU variables are encoded")
Reported-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Reported-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Hao Luo <haoluo@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-27 08:52:42 -03:00
Andrii Nakryiko 5e7ab5b9e0 btf_loader: Handle union forward declaration properly
Differentiate between struct and union forwards in BTF. BTF type
representing forward declaration (BTF_KIND_FWD) encodes whether the
forward declaration is for struct or union type by using kflag. So use
that kflag to create a proper internal representation of forward
declaration.

Tested with btfdiff on vmlinux:

  $ PAHOLE=build/pahole ./btfdiff ~/linux-build/default/vmlinux | wc -l
  0
  $

Also tested manually:

  $ cat test.c
  struct struct_fwd;

  union union_fwd;

  struct s {
          struct struct_fwd *f1;
          union union_fwd *f2;
  };

  int func(struct s *s) {
          return !!s->f1 + !!s->f2;
  }
  $ clang -g -target bpf -c test.c -o test.o
  $ bpftool btf dump file test.o | grep fwd_kind
  [6] FWD 'struct_fwd' fwd_kind=struct
  [8] FWD 'union_fwd' fwd_kind=union
  $ build/pahole -F btf test.o
  struct s {
          struct struct_fwd *        f1;                   /*     0     8 */
          union union_fwd *          f2;                   /*     8     8 */

          /* size: 16, cachelines: 1, members: 2 */
          /* last cacheline: 16 bytes */
  };

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-27 08:52:37 -03:00
Andrii Nakryiko ec3f944102 cmake: Make libbpf's Linux UAPI headers available to all binaries
Now that libbpf is used to implement deduplicated strings container, all
of the binaries will need linux/btf.h header to compile properly. libbpf
is distributed with its own copies of Linux UAPI headers, so use them
during compilation.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-26 16:50:08 -03:00
Andrii Nakryiko 8cac1c54c8 btf_encoder: Ignore zero-sized ELF symbols
It's legal for ELF symbol to have size 0, if it's size is unknown or
unspecified. Instead of erroring out, just ignore such symbols, as they can't
be a valid per-CPU variable anyways.

Reported-by: Érico Rolim <erico.erc@gmail.com>
Reported-by: Jiri Slaby <jirislaby@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Tested-by: Jiri Slaby <jirislaby@kernel.org>
Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1177921
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-23 13:37:21 -03:00
Andrii Nakryiko 040fd7f585 btf_encoder: Support cross-compiled ELF binaries with different endianness
Ensure that output BTF endianness corresponds to target ELF's endianness. This
makes it finally possible to use pahole to generate BTF for cross-compiled
kernels with different endianness.

Committer testing:

First cross build a s390x (Big Endian) vmlinux on a x86_64 (Little
Endian) workstation, notice the MSB/LSB marks:

On Fedora have these packages installed:

  $ rpm -qa | grep s390
  binutils-s390x-linux-gnu-2.34-2.fc32.x86_64
  gcc-c++-s390x-linux-gnu-9.2.1-3.fc32.1.x86_64
  gcc-s390x-linux-gnu-9.2.1-3.fc32.1.x86_64
  $

Some extra dependencies will be installed, then build the kernel using:

  $ make -j24 CROSS_COMPILE=s390x-linux-gnu- ARCH=s390 O=../build/s390x-v5.9.0+/

  Make sure you have:

  $ grep BTF=y ../build/s390x-v5.9.0+/.config
  CONFIG_DEBUG_INFO_BTF=y
  $

Hint, using 'make allmodconfig' will disable that, as:

  CONFIG_DEBUG_INFO_BTF:
  Depends on: DEBUG_INFO [=y] && !DEBUG_INFO_SPLIT [=n] && !DEBUG_INFO_REDUCED [=n] && (!GCC_PLUGIN_RANDSTRUCT [=n] || COMPILE_TEST [=n])

Then look at vmlinux files generated for s390x and x86_64:

  $ ls -la /home/acme/git/build/s390x-v5.9.0+/vmlinux
  -rwxrwxr-x. 1 acme acme 306441488 Oct 20 16:38 /home/acme/git/build/s390x-v5.9.0+/vmlinux
  $ file /home/acme/git/build/s390x-v5.9.0+/vmlinux
  /home/acme/git/build/s390x-v5.9.0+/vmlinux: ELF 64-bit MSB executable, IBM S/390, version 1 (SYSV), statically linked, BuildID[sha1]=bd46a0281b2bba450930ba95600765b6da9df117, with debug_info, not stripped
  $ file /home/acme/git/build/v5.9.0+/vmlinux
  /home/acme/git/build/v5.9.0+/vmlinux: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=1e9fd8f64e09bfc5dc8bc2a48e83301733adbf0a, with debug_info, not stripped
  $ readelf -SW /home/acme/git/build/s390x-v5.9.0+/vmlinux | grep BTF
    [16] .BTF              PROGBITS        0000000001e27dfc 1d28dfc 29cb26 00   A  0   0  1
    [17] .BTF_ids          PROGBITS        00000000020c4924 1fc5924 0000a8 00   A  0   0  1
  $ readelf -SW /home/acme/git/build/v5.9.0+/vmlinux | grep BTF
    [24] .BTF              PROGBITS        ffffffff824aa298 16aa298 34f615 00   A  0   0  1
    [25] .BTF_ids          PROGBITS        ffffffff827f98b0 19f98b0 000064 00   A  0   0  1
  $ btfdiff /home/acme/git/build/s390x-v5.9.0+/vmlinux
  $ btfdiff /home/acme/git/build/v5.9.0+/vmlinux
  $ pahole -F btf -C list_head /home/acme/git/build/s390x-v5.9.0+/vmlinux
  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 */
  };
  $ pahole -F btf -C list_head /home/acme/git/build/v5.9.0+/vmlinux
  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 */
  };
  $ pahole -F dwarf -C list_head /home/acme/git/build/s390x-v5.9.0+/vmlinux
  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 */
  };
  $ pahole -F dwarf -C list_head /home/acme/git/build/v5.9.0+/vmlinux
  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 */
  };
  $ pahole -F btf -C task_struct /home/acme/git/build/s390x-v5.9.0+/vmlinux > task_struct.s390x.txt
  $ pahole -F btf -C task_struct /home/acme/git/build/v5.9.0+/vmlinux > task_struct.x86_64.txt
  $ grep '^}' -B5 task_struct.s390x.txt

  	/* size: 11520, cachelines: 180, members: 243 */
  	/* sum members: 11179, holes: 19, sum holes: 205 */
  	/* sum bitfield members: 13 bits, bit holes: 2, sum bit holes: 51 bits */
  	/* padding: 128 */
  };
  $ grep '^}' -B5 task_struct.x86_64.txt

  	/* size: 11200, cachelines: 175, members: 224 */
  	/* sum members: 11075, holes: 17, sum holes: 109 */
  	/* sum bitfield members: 75 bits, bit holes: 2, sum bit holes: 53 bits */
  	/* paddings: 5, sum paddings: 22 */
  };
  $

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-21 08:07:43 -03:00
Andrii Nakryiko 29fce8dc85 strings: use BTF's string APIs for strings management
Switch strings container to using struct btf and its
btf__add_str()/btf__find_str() APIs, which do equivalent internal string
deduplication. This turns out to be a very significantly faster than using
tsearch functions. To satisfy CTF encoding use case, some hacky string size
fetching approach is utilized, as libbpf doesn't provide direct API to get
total string section size and to copy over just strings data section.

BEFORE:
         22,624.28 msec task-clock                #    1.000 CPUs utilized
                85      context-switches          #    0.004 K/sec
                 3      cpu-migrations            #    0.000 K/sec
           622,545      page-faults               #    0.028 M/sec
    68,177,206,387      cycles                    #    3.013 GHz                      (24.99%)
   114,370,031,619      instructions              #    1.68  insn per cycle           (25.01%)
    26,125,001,179      branches                  # 1154.733 M/sec                    (25.01%)
       458,861,243      branch-misses             #    1.76% of all branches          (25.00%)
    24,533,455,967      L1-dcache-loads           # 1084.386 M/sec                    (25.02%)
       973,500,214      L1-dcache-load-misses     #    3.97% of all L1-dcache hits    (25.05%)
       338,773,561      LLC-loads                 #   14.974 M/sec                    (25.02%)
        12,651,196      LLC-load-misses           #    3.73% of all LL-cache hits     (25.00%)

      22.628910615 seconds time elapsed

      21.341063000 seconds user
       1.283763000 seconds sys

AFTER:
         18,362.97 msec task-clock                #    1.000 CPUs utilized
                37      context-switches          #    0.002 K/sec
                 0      cpu-migrations            #    0.000 K/sec
           626,281      page-faults               #    0.034 M/sec
    52,480,619,000      cycles                    #    2.858 GHz                      (25.00%)
   104,736,434,384      instructions              #    2.00  insn per cycle           (25.01%)
    23,878,428,465      branches                  # 1300.358 M/sec                    (25.01%)
       252,669,685      branch-misses             #    1.06% of all branches          (25.03%)
    21,829,390,952      L1-dcache-loads           # 1188.772 M/sec                    (25.04%)
       638,086,339      L1-dcache-load-misses     #    2.92% of all L1-dcache hits    (25.02%)
       212,327,435      LLC-loads                 #   11.563 M/sec                    (25.00%)
        14,578,117      LLC-load-misses           #    6.87% of all LL-cache hits     (25.00%)

      18.364427347 seconds time elapsed

      16.985494000 seconds user
       1.377959000 seconds sys

Committer testing:

Before:

  $ perf stat -r5 pahole -J vmlinux

   Performance counter stats for 'pahole -J vmlinux' (5 runs):

            8,735.92 msec task-clock:u              #    0.998 CPUs utilized            ( +-  0.34% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
             353,978      page-faults:u             #    0.041 M/sec                    ( +-  0.00% )
      34,722,167,335      cycles:u                  #    3.975 GHz                      ( +-  0.12% )  (83.33%)
         555,981,118      stalled-cycles-frontend:u #    1.60% frontend cycles idle     ( +-  1.53% )  (83.33%)
       5,215,370,531      stalled-cycles-backend:u  #   15.02% backend cycles idle      ( +-  1.31% )  (83.33%)
      72,615,773,119      instructions:u            #    2.09  insn per cycle
                                                    #    0.07  stalled cycles per insn  ( +-  0.02% )  (83.34%)
      16,624,959,121      branches:u                # 1903.057 M/sec                    ( +-  0.01% )  (83.33%)
         229,962,327      branch-misses:u           #    1.38% of all branches          ( +-  0.07% )  (83.33%)

              8.7503 +- 0.0301 seconds time elapsed  ( +-  0.34% )

  $

After:

  $ perf stat -r5 pahole -J vmlinux

   Performance counter stats for 'pahole -J vmlinux' (5 runs):

            7,302.31 msec task-clock:u              #    0.998 CPUs utilized            ( +-  1.16% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
             355,884      page-faults:u             #    0.049 M/sec                    ( +-  0.00% )
      29,150,861,078      cycles:u                  #    3.992 GHz                      ( +-  0.35% )  (83.33%)
         478,705,326      stalled-cycles-frontend:u #    1.64% frontend cycles idle     ( +-  2.70% )  (83.33%)
       5,351,001,796      stalled-cycles-backend:u  #   18.36% backend cycles idle      ( +-  1.20% )  (83.33%)
      65,835,888,022      instructions:u            #    2.26  insn per cycle
                                                    #    0.08  stalled cycles per insn  ( +-  0.03% )  (83.33%)
      15,025,195,460      branches:u                # 2057.594 M/sec                    ( +-  0.05% )  (83.34%)
         141,209,214      branch-misses:u           #    0.94% of all branches          ( +-  0.15% )  (83.33%)

              7.3140 +- 0.0851 seconds time elapsed  ( +-  1.16% )

  $

16.04% less cycles, keep the patches coming! :-)

Had to add this patch tho:

  +++ b/dwarf_loader.c
  @@ -2159,7 +2159,7 @@ static unsigned long long dwarf_tag__orig_id(const struct tag *tag,
   static const char *dwarf__strings_ptr(const struct cu *cu __unused,
   				      strings_t s)
   {
  -	return strings__ptr(strings, s);
  +	return s ? strings__ptr(strings, s) : NULL;
   }

To keep preexisting behaviour and to do what the BTF specific
strings_ptr method does:

  static const char *btf_elf__strings_ptr(const struct cu *cu, strings_t s)
  {
          return btf_elf__string(cu->priv, s);
  }

  const char *btf_elf__string(struct btf_elf *btfe, uint32_t ref)
  {
          const char *s = btf__str_by_offset(btfe->btf, ref);

          return s && s[0] == '\0' ? NULL : s;
  }

With these adjustments, btfdiff on a vmlinux with BTF and DWARF is again
clean, i.e. pretty printing from BTF matches what we get when using
DWARF.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-20 17:17:51 -03:00
Arnaldo Carvalho de Melo 75f3520fed strings: Rename strings.h to avoid clashing with /usr/include/strings.h
This was detected with:

  In file included from /home/acme/git/pahole/strings.h:9,
                   from /usr/include/string.h:432,
                   from /home/acme/git/pahole/lib/bpf/src/libbpf_common.h:12,
                   from /home/acme/git/pahole/lib/bpf/src/libbpf.h:20,
                   from /home/acme/git/pahole/lib/bpf/src/ringbuf.c:20:
  /home/acme/git/pahole/lib/bpf/src/btf.h:33:11: error: expected ‘;’ before ‘void’
     33 | LIBBPF_API void btf__free(struct btf *btf);
        |           ^~~~~
        |           ;

libbpf_common.h has:

  #include <string.h>

  #ifndef LIBBPF_API
  #define LIBBPF_API __attribute__((visibility("default")))
  #endif

So before defining LIBBPF_API it includes libc's string.h that in turn
includes pahole's strings.h and now it includes:

  #include "lib/bpf/src/btf.h"

That will need the LIBBPF_API, b00m.

So lets just rename pahole's strings.h to pahole_strings.h to avoid this
pitfall.

This patch was moved to before this problem takes place so that we keep
everything bisectable.

Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-20 17:11:34 -03:00
Andrii Nakryiko bba7151e0f dwarf_loader: increase the size of lookup hash map
One of the primary use cases for using pahole is BTF deduplication during
Linux kernel build. That means that DWARF contains more than 5 million types
is loaded. So using a hash map with a small number of buckets is quite
expensive due to hash collisions. This patch bumps the size of the hash map
and reduces overhead of this part of the DWARF loading process.

This shaves off about 1 second out of about 20 seconds total for Linux BTF
dedup.

Committer testing:

Before:

  $ perf stat -r5 pahole -J vmlinux

   Performance counter stats for 'pahole -J vmlinux' (5 runs):

            8,953.80 msec task-clock:u              #    0.998 CPUs utilized            ( +-  0.09% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
             353,855      page-faults:u             #    0.040 M/sec                    ( +-  0.00% )
      35,775,730,539      cycles:u                  #    3.996 GHz                      ( +-  0.07% )  (83.33%)
         579,534,836      stalled-cycles-frontend:u #    1.62% frontend cycles idle     ( +-  2.21% )  (83.33%)
       5,719,840,144      stalled-cycles-backend:u  #   15.99% backend cycles idle      ( +-  0.93% )  (83.33%)
      73,035,744,786      instructions:u            #    2.04  insn per cycle
                                                    #    0.08  stalled cycles per insn  ( +-  0.02% )  (83.34%)
      16,798,017,844      branches:u                # 1876.077 M/sec                    ( +-  0.05% )  (83.33%)
         237,777,143      branch-misses:u           #    1.42% of all branches          ( +-  0.15% )  (83.34%)

             8.97077 +- 0.00803 seconds time elapsed  ( +-  0.09% )

  $

After:

  $ perf stat -r5 pahole -J vmlinux

   Performance counter stats for 'pahole -J vmlinux' (5 runs):

            8,735.92 msec task-clock:u              #    0.998 CPUs utilized            ( +-  0.34% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
             353,978      page-faults:u             #    0.041 M/sec                    ( +-  0.00% )
      34,722,167,335      cycles:u                  #    3.975 GHz                      ( +-  0.12% )  (83.33%)
         555,981,118      stalled-cycles-frontend:u #    1.60% frontend cycles idle     ( +-  1.53% )  (83.33%)
       5,215,370,531      stalled-cycles-backend:u  #   15.02% backend cycles idle      ( +-  1.31% )  (83.33%)
      72,615,773,119      instructions:u            #    2.09  insn per cycle
                                                    #    0.07  stalled cycles per insn  ( +-  0.02% )  (83.34%)
      16,624,959,121      branches:u                # 1903.057 M/sec                    ( +-  0.01% )  (83.33%)
         229,962,327      branch-misses:u           #    1.38% of all branches          ( +-  0.07% )  (83.33%)

              8.7503 +- 0.0301 seconds time elapsed  ( +-  0.34% )

  $

2.94% less cycles, good :-)

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-09 13:05:43 -03:00
Andrii Nakryiko 2e719cca66 btf_encoder: revamp how per-CPU variables are encoded
Right now to encode per-CPU variables in BTF, pahole iterates complete vmlinux
symbol table for each CU. There are 2500 CUs for a typical kernel image.
Overall, to encode 287 per-CPU variables pahole spends more than 10% of its CPU
budget, this is incredibly wasteful.

This patch revamps how this is done. Now it pre-processes symbol table once
before any of per-CU processing starts. It remembers each per-CPU variable
symbol, including its address, size, and name. Then during processing each CU,
binary search is used to correlate DWARF variable with per-CPU symbols and
figure out if variable belongs to per-CPU data section. If the match is found,
BTF_KIND_VAR is emitted and var_secinfo is recorded, just like before. At the
very end, after all CUs are processed, BTF_KIND_DATASEC is emitted with sorted
variables.

This change makes per-CPU variables generation overhead pretty negligible and
returns back about 10% of CPU usage.

Performance counter stats for './pahole -J /home/andriin/linux-build/default/vmlinux':

BEFORE:
      19.160149000 seconds user
       1.304873000 seconds sys

         24,114.05 msec task-clock                #    0.999 CPUs utilized
                83      context-switches          #    0.003 K/sec
                 0      cpu-migrations            #    0.000 K/sec
           622,417      page-faults               #    0.026 M/sec
    72,897,315,125      cycles                    #    3.023 GHz                      (25.02%)
   127,807,316,959      instructions              #    1.75  insn per cycle           (25.01%)
    29,087,179,117      branches                  # 1206.234 M/sec                    (25.01%)
       464,105,921      branch-misses             #    1.60% of all branches          (25.01%)
    30,252,119,368      L1-dcache-loads           # 1254.543 M/sec                    (25.01%)
     1,156,336,207      L1-dcache-load-misses     #    3.82% of all L1-dcache hits    (25.05%)
       343,373,503      LLC-loads                 #   14.240 M/sec                    (25.02%)
        12,044,977      LLC-load-misses           #    3.51% of all LL-cache hits     (25.01%)

      24.136198321 seconds time elapsed

      22.729693000 seconds user
       1.384859000 seconds sys

AFTER:
      16.781455000 seconds user
       1.343956000 seconds sys

         23,398.77 msec task-clock                #    1.000 CPUs utilized
                86      context-switches          #    0.004 K/sec
                 0      cpu-migrations            #    0.000 K/sec
           622,420      page-faults               #    0.027 M/sec
    68,395,641,468      cycles                    #    2.923 GHz                      (25.05%)
   114,241,327,034      instructions              #    1.67  insn per cycle           (25.01%)
    26,330,711,718      branches                  # 1125.303 M/sec                    (25.01%)
       465,926,869      branch-misses             #    1.77% of all branches          (25.00%)
    24,662,984,772      L1-dcache-loads           # 1054.029 M/sec                    (25.00%)
     1,054,052,064      L1-dcache-load-misses     #    4.27% of all L1-dcache hits    (25.00%)
       340,970,622      LLC-loads                 #   14.572 M/sec                    (25.00%)
        16,032,297      LLC-load-misses           #    4.70% of all LL-cache hits     (25.03%)

      23.402259654 seconds time elapsed

      21.916437000 seconds user
       1.482826000 seconds sys

Committer testing:

  $ grep 'model name' -m1 /proc/cpuinfo
  model name	: AMD Ryzen 9 3900X 12-Core Processor
  $

Before:

  $ perf stat -r5 pahole -J vmlinux

   Performance counter stats for 'pahole -J vmlinux' (5 runs):

            9,730.28 msec task-clock:u              #    0.998 CPUs utilized            ( +-  0.54% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
             353,854      page-faults:u             #    0.036 M/sec                    ( +-  0.00% )
      39,721,726,459      cycles:u                  #    4.082 GHz                      ( +-  0.07% )  (83.33%)
         626,010,654      stalled-cycles-frontend:u #    1.58% frontend cycles idle     ( +-  0.91% )  (83.33%)
       7,518,333,691      stalled-cycles-backend:u  #   18.93% backend cycles idle      ( +-  0.56% )  (83.33%)
      85,477,123,093      instructions:u            #    2.15  insn per cycle
                                                    #    0.09  stalled cycles per insn  ( +-  0.02% )  (83.34%)
      19,346,085,683      branches:u                # 1988.235 M/sec                    ( +-  0.03% )  (83.34%)
         237,291,787      branch-misses:u           #    1.23% of all branches          ( +-  0.15% )  (83.33%)

              9.7465 +- 0.0524 seconds time elapsed  ( +-  0.54% )

  $

After:

  $ perf stat -r5 pahole -J vmlinux

   Performance counter stats for 'pahole -J vmlinux' (5 runs):

            8,953.80 msec task-clock:u              #    0.998 CPUs utilized            ( +-  0.09% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
             353,855      page-faults:u             #    0.040 M/sec                    ( +-  0.00% )
      35,775,730,539      cycles:u                  #    3.996 GHz                      ( +-  0.07% )  (83.33%)
         579,534,836      stalled-cycles-frontend:u #    1.62% frontend cycles idle     ( +-  2.21% )  (83.33%)
       5,719,840,144      stalled-cycles-backend:u  #   15.99% backend cycles idle      ( +-  0.93% )  (83.33%)
      73,035,744,786      instructions:u            #    2.04  insn per cycle
                                                    #    0.08  stalled cycles per insn  ( +-  0.02% )  (83.34%)
      16,798,017,844      branches:u                # 1876.077 M/sec                    ( +-  0.05% )  (83.33%)
         237,777,143      branch-misses:u           #    1.42% of all branches          ( +-  0.15% )  (83.34%)

             8.97077 +- 0.00803 seconds time elapsed  ( +-  0.09% )

  $

Indeed, about 10% shaved, not bad.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Hao Luo <haoluo@google.com>
Cc: Oleg Rombakh <olegrom@google.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-09 12:57:35 -03:00
Andrii Nakryiko 0258a47ef9 btf_encoder: Discard CUs after BTF encoding
When doing BTF encoding/deduping, DWARF CUs are never used after BTF encoding
is done, so there is no point in wasting memory and keeping them in memory. So
discard them immediately.

Committer testing:

  $ pahole -J vmlinux
  $ ./btfdiff vmlinux
  $

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-09 12:49:42 -03:00
Andrii Nakryiko 3c913e18b2 btf_encoder: Fix emitting __ARRAY_SIZE_TYPE__ as index range type
Fix the logic of determining if __ARRAY_SIZE_TYPE__ needs to be emitted.
Previously, such type could be emitted unnecessarily due to some
particular CU not having an int type in it. That would happen even if
there was no array type in that CU. Fix it by keeping track of 'int'
type across CUs and only emitting __ARRAY_SIZE_TYPE__ if a given CU has
array type, but we still haven't found 'int' type.

Testing against vmlinux shows that now there are no __ARRAY_SIZE_TYPE__
integers emitted.

Committer testing:

  $ pahole -J vmlinux
  $ ./btfdiff vmlinux
  $

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-09 12:49:40 -03:00
Andrii Nakryiko 48efa92933 btf_encoder: Use libbpf APIs to encode BTF type info
Switch to use libbpf's BTF writing APIs to encode BTF. This reconciles
btf_elf's use of internal struct btf from libbpf for both loading and
encoding BTF type info. This change also saves a considerable amount of
memory used for DWARF to BTF conversion due to avoiding extra memory
copy between gobuffers and libbpf's struct btf. Now that pahole uses
libbpf's struct btf, it's possible to further utilize libbpf's features
and APIs, e.g., for handling endianness conversion, for dumping raw BTF
type info during encoding. These features might be implemented in the
follow up patches.

Committer notes:

Built with 'cmake -DCMAKE_BUILD_TYPE=Release'

Before:

  $ cp ~/git/build/bpf-next-v5.9.0-rc8+/vmlinux .
  $ perf stat -r5 pahole -J vmlinux

   Performance counter stats for 'pahole -J vmlinux' (5 runs):

           10,065.20 msec task-clock:u              #    0.998 CPUs utilized            ( +-  0.68% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
             514,596      page-faults:u             #    0.051 M/sec                    ( +-  0.00% )
      40,098,447,225      cycles:u                  #    3.984 GHz                      ( +-  0.26% )  (83.33%)
         547,247,149      stalled-cycles-frontend:u #    1.36% frontend cycles idle     ( +-  2.00% )  (83.33%)
       6,493,462,167      stalled-cycles-backend:u  #   16.19% backend cycles idle      ( +-  1.53% )  (83.33%)
      86,338,929,286      instructions:u            #    2.15  insn per cycle
                                                    #    0.08  stalled cycles per insn  ( +-  0.01% )  (83.34%)
      19,859,060,127      branches:u                # 1973.043 M/sec                    ( +-  0.02% )  (83.33%)
         288,389,742      branch-misses:u           #    1.45% of all branches          ( +-  0.13% )  (83.33%)

             10.0831 +- 0.0683 seconds time elapsed  ( +-  0.68% )

  $

After:

  $ perf stat -r5 pahole -J vmlinux

   Performance counter stats for 'pahole -J vmlinux' (5 runs):

           10,043.94 msec task-clock:u              #    0.998 CPUs utilized            ( +-  0.69% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
             412,035      page-faults:u             #    0.041 M/sec                    ( +-  0.00% )
      39,985,610,202      cycles:u                  #    3.981 GHz                      ( +-  0.18% )  (83.33%)
         657,352,766      stalled-cycles-frontend:u #    1.64% frontend cycles idle     ( +-  2.79% )  (83.33%)
       7,387,740,861      stalled-cycles-backend:u  #   18.48% backend cycles idle      ( +-  1.65% )  (83.33%)
      85,926,053,845      instructions:u            #    2.15  insn per cycle
                                                    #    0.09  stalled cycles per insn  ( +-  0.04% )  (83.34%)
      19,428,047,875      branches:u                # 1934.305 M/sec                    ( +-  0.05% )  (83.33%)
         240,156,838      branch-misses:u           #    1.24% of all branches          ( +-  0.14% )  (83.34%)

             10.0609 +- 0.0696 seconds time elapsed  ( +-  0.69% )

  $

  $ ./btfdiff vmlinux
  $

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-09 12:49:37 -03:00
Andrii Nakryiko 5d863aa7ce btf_loader: Use libbpf to load BTF
Switch BTF loading to completely use libbpf's own struct btf and related
APIs.

BTF encoding is still happening with pahole's own code, so these two
code paths are not sharing anything now. String fetching is happening
based on whether btfe->strings were set to non-NULL pointer by
btf_encoder.

Committer testing:

  $ cp ~/git/build/bpf-next-v5.9.0-rc8+/vmlinux .
  $ readelf -SW vmlinux  | grep BTF
    [24] .BTF      PROGBITS  ffffffff82494ac0 1694ac0 340207 00   A  0  0  1
    [25] .BTF_ids  PROGBITS  ffffffff827d4cc8 19d4cc8 0000a4 00   A  0  0  1
  $ ./btfdiff vmlinux
  $

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-09 12:43:42 -03:00
Andrii Nakryiko 0a9b89910e dwarves: Expose and maintain active debug info loader operations
Maintain a pointer to debug_fmt_ops corresponding to currently used debug info
format loader (DWARF, BTF, or CTF), to allow various parts of libdwarves to do
things like resolve string offset to actual string pointer in
a format-agnostic format. This allows to, say, load DWARF debug info, and use
it for BTF generation, without either of them making assumptions about how
strings are actually stored internally.

This is going to be used in the next patch to allow BTF loader and encoder to
use a very different way of storing strings (not a global shared gobuffer).

Committer notes:

Since it is available in multiple object files, add a dwarves__ prefix
namespace and add an extern for it in dwarves.h.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-09 12:43:40 -03:00
Andrii Nakryiko 7bc2dd07d5 btf_encoder: detect BTF encoding errors and exit
Don't silently swallow BTF encoding errors and continue onto next CU. If
any of CU fails to properly encode BTF, exit with an error message.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-09 12:43:36 -03:00
Andrii Nakryiko c35b7fa52c libbpf: Update to latest libbpf version
Pull in BTF writer APIs.

Committer testing:

  $ rm -rf build
  $ mkdir build
  $ cd build
  $ cmake ..
  -- The C compiler identification is GNU 10.2.1
  -- Check for working C compiler: /usr/lib64/ccache/cc
  -- Check for working C compiler: /usr/lib64/ccache/cc - works
  -- Detecting C compiler ABI info
  -- Detecting C compiler ABI info - done
  -- Detecting C compile features
  -- Detecting C compile features - done
  -- Checking availability of DWARF and ELF development libraries
  -- Looking for dwfl_module_build_id in elf
  -- Looking for dwfl_module_build_id in elf - found
  -- Found dwarf.h header: /usr/include
  -- Found elfutils/libdw.h header: /usr/include
  -- Found libdw library: /usr/lib64/libdw.so
  -- Found libelf library: /usr/lib64/libelf.so
  -- Checking availability of DWARF and ELF development libraries - done
  -- Found ZLIB: /usr/lib64/libz.so (found version "1.2.11")
  -- Submodule update
  From https://github.com/libbpf/libbpf
   * [new branch]                        libbpf-0.1.1-xdp-bug-fix -> origin/libbpf-0.1.1-xdp-bug-fix
     583bddce6b93bafa..b6dd2f2b7df4d3bd  master     -> origin/master
   * [new tag]                           v0.1.1     -> v0.1.1
   * [new tag]                           v0.0.8     -> v0.0.8
   * [new tag]                           v0.0.9     -> v0.0.9
   * [new tag]                           v0.1.0     -> v0.1.0
  Submodule path 'lib/bpf': checked out 'ff797cc905d9c5fe9acab92d2da127342b20f80f'
  -- Submodule update - done
  -- Performing Test HAVE_REALLOCARRAY_SUPPORT
  -- Performing Test HAVE_REALLOCARRAY_SUPPORT - Success
  -- Configuring done
  -- Generating done
  -- Build files have been written to: /home/acme/git/pahole/build
  $
  $ cd ..
  $ ./btfdiff vmlinux
  $
  $ cat fullcircle
  #!/bin/bash
  # SPDX-License-Identifier: GPL-2.0-only
  # Copyright © 2019 Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
  # Use pfunct to produce compilable output from a object, then do a codiff -s
  # To see if the type information generated from source code generated
  # from type information in a file compiled from the original source code matches.

  if [ $# -eq 0 ] ; then
  	echo "Usage: fullcircle <filename_with_type_info>"
  	exit 1
  fi

  file=$1

  nr_cus=$(readelf -wi ${file} | grep DW_TAG_compile_unit | wc -l)
  if [ $nr_cus -gt 1 ]; then
  	exit 0
  fi

  c_output=$(mktemp /tmp/fullcircle.XXXXXX.c)
  o_output=$(mktemp /tmp/fullcircle.XXXXXX.o)
  pfunct_bin=${PFUNCT-"pfunct"}
  codiff_bin=${CODIFF-"codiff"}

  # See how your DW_AT_producer looks like and find the
  # right regexp to get after the GCC version string, this one
  # seems good enough for Red Hat/Fedora/CentOS that look like:
  #
  #   DW_AT_producer    : (indirect string, offset: 0x3583): GNU C89 8.2.1 20181215 (Red Hat 8.2.1-6) -mno-sse -mno-mmx
  #
  # So we need from -mno-sse onwards

  CFLAGS=$(readelf -wi $file | grep -w DW_AT_producer | sed -r      's/.*\)( -[[:alnum:]]+.*)+/\1/g')

  # Check if we managed to do the sed or if this is something like GNU AS
  [ "${CFLAGS/DW_AT_producer/}" != "${CFLAGS}" ] && exit

  ${pfunct_bin} --compile $file > $c_output
  gcc $CFLAGS -c -g $c_output -o $o_output
  ${codiff_bin} -q -s $file $o_output

  rm -f $c_output $o_output
  exit 0
  [acme@five pahole]$ cp ~/git/build/bpf-next-v5.9.0-rc8+/net/ipv4/tcp_ipv4.o  .
  [acme@five pahole]$ readelf -SW tcp_ipv4.o  | grep BTF
  [acme@five pahole]$ pahole -J tcp_ipv4.o
  [acme@five pahole]$ readelf -SW tcp_ipv4.o  | grep BTF
    [105] .BTF              PROGBITS        0000000000000000 0fcf68 03ff6e 00      0   0  1
  [acme@five pahole]$ ./fullcircle tcp_ipv4.o
  [acme@five pahole]$ pahole -F btf -C tcp_sock tcp_ipv4.o
  struct tcp_sock {
  	struct inet_connection_sock inet_conn;           /*     0  1376 */
  	/* --- cacheline 21 boundary (1344 bytes) was 32 bytes ago --- */
  	u16                        tcp_header_len;       /*  1376     2 */
  	u16                        gso_segs;             /*  1378     2 */
  	__be32                     pred_flags;           /*  1380     4 */
  	u64                        bytes_received;       /*  1384     8 */
  	u32                        segs_in;              /*  1392     4 */
  	u32                        data_segs_in;         /*  1396     4 */
  	u32                        rcv_nxt;              /*  1400     4 */
  	u32                        copied_seq;           /*  1404     4 */
  	/* --- cacheline 22 boundary (1408 bytes) --- */
  	u32                        rcv_wup;              /*  1408     4 */
  	u32                        snd_nxt;              /*  1412     4 */
  	u32                        segs_out;             /*  1416     4 */
  	u32                        data_segs_out;        /*  1420     4 */
  	u64                        bytes_sent;           /*  1424     8 */
  	u64                        bytes_acked;          /*  1432     8 */
  	u32                        dsack_dups;           /*  1440     4 */
  	u32                        snd_una;              /*  1444     4 */
  	u32                        snd_sml;              /*  1448     4 */
  	u32                        rcv_tstamp;           /*  1452     4 */
  	u32                        lsndtime;             /*  1456     4 */
  	u32                        last_oow_ack_time;    /*  1460     4 */
  	u32                        compressed_ack_rcv_nxt; /*  1464     4 */
  	u32                        tsoffset;             /*  1468     4 */
  	/* --- cacheline 23 boundary (1472 bytes) --- */
  	struct list_head           tsq_node;             /*  1472    16 */
  	struct list_head           tsorted_sent_queue;   /*  1488    16 */
  	u32                        snd_wl1;              /*  1504     4 */
  	u32                        snd_wnd;              /*  1508     4 */
  	u32                        max_window;           /*  1512     4 */
  	u32                        mss_cache;            /*  1516     4 */
  	u32                        window_clamp;         /*  1520     4 */
  	u32                        rcv_ssthresh;         /*  1524     4 */
  	struct tcp_rack            rack;                 /*  1528    24 */

  	/* XXX last struct has 2 bytes of padding */

  	/* --- cacheline 24 boundary (1536 bytes) was 16 bytes ago --- */
  	u16                        advmss;               /*  1552     2 */
  	u8                         compressed_ack;       /*  1554     1 */
  	u8                         dup_ack_counter:2;    /*  1555: 0  1 */
  	u8                         tlp_retrans:1;        /*  1555: 2  1 */
  	u8                         unused:5;             /*  1555: 3  1 */
  	u32                        chrono_start;         /*  1556     4 */
  	u32                        chrono_stat[3];       /*  1560    12 */
  	u8                         chrono_type:2;        /*  1572: 0  1 */
  	u8                         rate_app_limited:1;   /*  1572: 2  1 */
  	u8                         fastopen_connect:1;   /*  1572: 3  1 */
  	u8                         fastopen_no_cookie:1; /*  1572: 4  1 */
  	u8                         is_sack_reneg:1;      /*  1572: 5  1 */
  	u8                         fastopen_client_fail:2; /*  1572: 6  1 */
  	u8                         nonagle:4;            /*  1573: 0  1 */
  	u8                         thin_lto:1;           /*  1573: 4  1 */
  	u8                         recvmsg_inq:1;        /*  1573: 5  1 */
  	u8                         repair:1;             /*  1573: 6  1 */
  	u8                         frto:1;               /*  1573: 7  1 */
  	u8                         repair_queue;         /*  1574     1 */
  	u8                         save_syn:2;           /*  1575: 0  1 */
  	u8                         syn_data:1;           /*  1575: 2  1 */
  	u8                         syn_fastopen:1;       /*  1575: 3  1 */
  	u8                         syn_fastopen_exp:1;   /*  1575: 4  1 */
  	u8                         syn_fastopen_ch:1;    /*  1575: 5  1 */
  	u8                         syn_data_acked:1;     /*  1575: 6  1 */
  	u8                         is_cwnd_limited:1;    /*  1575: 7  1 */
  	u32                        tlp_high_seq;         /*  1576     4 */
  	u32                        tcp_tx_delay;         /*  1580     4 */
  	u64                        tcp_wstamp_ns;        /*  1584     8 */
  	u64                        tcp_clock_cache;      /*  1592     8 */
  	/* --- cacheline 25 boundary (1600 bytes) --- */
  	u64                        tcp_mstamp;           /*  1600     8 */
  	u32                        srtt_us;              /*  1608     4 */
  	u32                        mdev_us;              /*  1612     4 */
  	u32                        mdev_max_us;          /*  1616     4 */
  	u32                        rttvar_us;            /*  1620     4 */
  	u32                        rtt_seq;              /*  1624     4 */
  	struct minmax              rtt_min;              /*  1628    24 */
  	u32                        packets_out;          /*  1652     4 */
  	u32                        retrans_out;          /*  1656     4 */
  	u32                        max_packets_out;      /*  1660     4 */
  	/* --- cacheline 26 boundary (1664 bytes) --- */
  	u32                        max_packets_seq;      /*  1664     4 */
  	u16                        urg_data;             /*  1668     2 */
  	u8                         ecn_flags;            /*  1670     1 */
  	u8                         keepalive_probes;     /*  1671     1 */
  	u32                        reordering;           /*  1672     4 */
  	u32                        reord_seen;           /*  1676     4 */
  	u32                        snd_up;               /*  1680     4 */
  	struct tcp_options_received rx_opt;              /*  1684    24 */
  	u32                        snd_ssthresh;         /*  1708     4 */
  	u32                        snd_cwnd;             /*  1712     4 */
  	u32                        snd_cwnd_cnt;         /*  1716     4 */
  	u32                        snd_cwnd_clamp;       /*  1720     4 */
  	u32                        snd_cwnd_used;        /*  1724     4 */
  	/* --- cacheline 27 boundary (1728 bytes) --- */
  	u32                        snd_cwnd_stamp;       /*  1728     4 */
  	u32                        prior_cwnd;           /*  1732     4 */
  	u32                        prr_delivered;        /*  1736     4 */
  	u32                        prr_out;              /*  1740     4 */
  	u32                        delivered;            /*  1744     4 */
  	u32                        delivered_ce;         /*  1748     4 */
  	u32                        lost;                 /*  1752     4 */
  	u32                        app_limited;          /*  1756     4 */
  	u64                        first_tx_mstamp;      /*  1760     8 */
  	u64                        delivered_mstamp;     /*  1768     8 */
  	u32                        rate_delivered;       /*  1776     4 */
  	u32                        rate_interval_us;     /*  1780     4 */
  	u32                        rcv_wnd;              /*  1784     4 */
  	u32                        write_seq;            /*  1788     4 */
  	/* --- cacheline 28 boundary (1792 bytes) --- */
  	u32                        notsent_lowat;        /*  1792     4 */
  	u32                        pushed_seq;           /*  1796     4 */
  	u32                        lost_out;             /*  1800     4 */
  	u32                        sacked_out;           /*  1804     4 */
  	struct hrtimer             pacing_timer;         /*  1808    64 */

  	/* XXX last struct has 4 bytes of padding */

  	/* --- cacheline 29 boundary (1856 bytes) was 16 bytes ago --- */
  	struct hrtimer             compressed_ack_timer; /*  1872    64 */

  	/* XXX last struct has 4 bytes of padding */

  	/* --- cacheline 30 boundary (1920 bytes) was 16 bytes ago --- */
  	struct sk_buff *           lost_skb_hint;        /*  1936     8 */
  	struct sk_buff *           retransmit_skb_hint;  /*  1944     8 */
  	struct rb_root             out_of_order_queue;   /*  1952     8 */
  	struct sk_buff *           ooo_last_skb;         /*  1960     8 */
  	struct tcp_sack_block      duplicate_sack[1];    /*  1968     8 */
  	struct tcp_sack_block      selective_acks[4];    /*  1976    32 */
  	/* --- cacheline 31 boundary (1984 bytes) was 24 bytes ago --- */
  	struct tcp_sack_block      recv_sack_cache[4];   /*  2008    32 */
  	struct sk_buff *           highest_sack;         /*  2040     8 */
  	/* --- cacheline 32 boundary (2048 bytes) --- */
  	int                        lost_cnt_hint;        /*  2048     4 */
  	u32                        prior_ssthresh;       /*  2052     4 */
  	u32                        high_seq;             /*  2056     4 */
  	u32                        retrans_stamp;        /*  2060     4 */
  	u32                        undo_marker;          /*  2064     4 */
  	int                        undo_retrans;         /*  2068     4 */
  	u64                        bytes_retrans;        /*  2072     8 */
  	u32                        total_retrans;        /*  2080     4 */
  	u32                        urg_seq;              /*  2084     4 */
  	unsigned int               keepalive_time;       /*  2088     4 */
  	unsigned int               keepalive_intvl;      /*  2092     4 */
  	int                        linger2;              /*  2096     4 */
  	u8                         bpf_sock_ops_cb_flags; /*  2100     1 */

  	/* XXX 1 byte hole, try to pack */

  	u16                        timeout_rehash;       /*  2102     2 */
  	u32                        rcv_ooopack;          /*  2104     4 */
  	u32                        rcv_rtt_last_tsecr;   /*  2108     4 */
  	/* --- cacheline 33 boundary (2112 bytes) --- */
  	struct {
  		u32                rtt_us;               /*  2112     4 */
  		u32                seq;                  /*  2116     4 */
  		u64                time;                 /*  2120     8 */
  	} rcv_rtt_est;                                   /*  2112    16 */
  	struct {
  		u32                space;                /*  2128     4 */
  		u32                seq;                  /*  2132     4 */
  		u64                time;                 /*  2136     8 */
  	} rcvq_space;                                    /*  2128    16 */
  	struct {
  		u32                probe_seq_start;      /*  2144     4 */
  		u32                probe_seq_end;        /*  2148     4 */
  	} mtu_probe;                                     /*  2144     8 */
  	u32                        mtu_info;             /*  2152     4 */
  	bool                       is_mptcp;             /*  2156     1 */
  	bool                       syn_smc;              /*  2157     1 */

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

  	const struct tcp_sock_af_ops  * af_specific;     /*  2160     8 */
  	struct tcp_md5sig_info *   md5sig_info;          /*  2168     8 */
  	/* --- cacheline 34 boundary (2176 bytes) --- */
  	struct tcp_fastopen_request * fastopen_req;      /*  2176     8 */
  	struct request_sock *      fastopen_rsk;         /*  2184     8 */
  	struct saved_syn *         saved_syn;            /*  2192     8 */

  	/* size: 2200, cachelines: 35, members: 140 */
  	/* sum members: 2193, holes: 2, sum holes: 3 */
  	/* sum bitfield members: 32 bits (4 bytes) */
  	/* paddings: 3, sum paddings: 10 */
  	/* last cacheline: 24 bytes */
  };
  $ pahole -F btf -C tcp_sock tcp_ipv4.o  > tcp_sock.o.before
  $

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: bpf@vger.kernel.org
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-08 14:36:51 -03:00
Arnaldo Carvalho de Melo ef4f971a9c dwarf_loader: Conditionally define DW_AT_alignment
As there are distros where this isn't available, such as opensuse:15.2

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-08 10:17:33 -03:00
Arnaldo Carvalho de Melo cc3f9dce33 pahole: Implement --packed
To show just packed structs.

For instance, here are the top packed structures in the Linux kernel,
using BTF data:

  $ pahole --packed --sizes | sort -k2 -nr | head
  e820_table		64004	0
  boot_params		 4096	0
  btrfs_super_block	 3531	0
  efi_variable		 2084	0
  ntb_info_regs		  800	0
  tboot			  568	0
  _legacy_mbr		  512	0
  disklabel		  512	0
  btrfs_root_item	  439	0
  saved_context		  317	0
  $

If you then look at:

  $ pahole e820_table
  struct e820_table {
  	__u32                      nr_entries;           /*     0     4 */
  	struct e820_entry          entries[3200];        /*     4 64000 */

  	/* size: 64004, cachelines: 1001, members: 2 */
  	/* last cacheline: 4 bytes */
  } __attribute__((__packed__));
  $

In arch/x86/include/asm/e820/types.h we have:

  /*
   * The whole array of E820 entries:
   */
  struct e820_table {
          __u32 nr_entries;
          struct e820_entry entries[E820_MAX_ENTRIES];
  };

I.e. no explicit __packed__ attributes, but if we expand this a bit:

  $ pahole -E e820_table
  struct e820_table {
  	/* typedef __u32 */ unsigned int               nr_entries;                       /*     0     4 */
  	struct e820_entry {
  		/* typedef u64 -> __u64 */ long long unsigned int addr;                  /*     4     8 */
  		/* typedef u64 -> __u64 */ long long unsigned int size;                  /*    12     8 */
  		enum e820_type     type;                                                 /*    20     4 */
  	} __attribute__((__packed__)) entries[3200]; /*     4 64000 */

  	/* size: 64004, cachelines: 1001, members: 2 */
  	/* last cacheline: 4 bytes */
  } __attribute__((__packed__));
  $

We see that is that entries member that is packed, because:

  $ pahole e820_entry
  struct e820_entry {
  	u64                        addr;                 /*     0     8 */
  	u64                        size;                 /*     8     8 */
  	enum e820_type             type;                 /*    16     4 */

  	/* size: 20, cachelines: 1, members: 3 */
  	/* last cacheline: 20 bytes */
  } __attribute__((__packed__));
  $

In arch/x86/include/asm/e820/types.h we have:

  /*
   * A single E820 map entry, describing a memory range of [addr...addr+size-1],
   * of 'type' memory type:
   *
   * (We pack it because there can be thousands of them on large systems.)
   */
  struct e820_entry {
          u64                     addr;
          u64                     size;
          enum e820_type          type;
  } __attribute__((packed));

So yeah, it is there, BTF doesn't explicitly states it is packed (as
DWARF does) and pahole was able to infer that correctly.

Tested-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-08 10:11:31 -03:00
Arnaldo Carvalho de Melo 08f49262f4 man-pages: Fix 'coimbine' typo
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-08 09:10:34 -03:00
Arnaldo Carvalho de Melo fdc639188c dwarves: Prep v1.18
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-02 17:29:59 -03:00
Arnaldo Carvalho de Melo 70c3e66970 spec: Set the build type to 'Release'
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-02 17:29:21 -03:00
Zamir SUN 399376eba8 spec: Use more recent cmake rpm macros to fix build in fedora
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1863459
Signed-off-by: Zamir SUN <sztsian@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-10-02 17:24:03 -03:00