Commit Graph

1403 Commits

Author SHA1 Message Date
Arnaldo Carvalho de Melo ab714acec8 pahole: Support zero sized base type arrays
Like the one in:

  $ pahole -C perf_record_sample ~/bin/perf
  struct perf_record_sample {
  	struct perf_event_header   header;               /*     0     8 */
  	__u64                      array[];              /*     8     0 */

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

So now we get those:

  $ perf report -D
  <SNIP>
  0x420 [0x60]: event: 10
  . ... raw event: size 96 bytes
  .  0000:  0a 00 00 00 02 00 60 00 50 7e 00 00 50 7e 00 00  ......`.P~..P~..
  .  0010:  00 90 b6 d8 ff 7f 00 00 00 20 00 00 00 00 00 00  ..<B6><D8><FF>.... ......
  .  0020:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  .  0030:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  .  0040:  05 00 00 00 02 10 00 00 5b 76 64 73 6f 5d 00 00  ........[vdso]..
  .  0050:  50 7e 00 00 50 7e 00 00 e7 c5 2a c3 aa 90 01 00  P~..P~..<E7><C5>*<C3><AA>...

  440538069911015 0x420 [0x60]: PERF_RECORD_MMAP2 32336/32336: [0x7fffd8b69000(0x2000) @ 0 00:00 0 0]: r-xp [vdso]

  0x480 [0x28]: event: 9
  . ... raw event: size 40 bytes
  .  0000:  09 00 00 00 01 40 28 00 27 0b c0 88 ff ff ff ff  .....@(.'.<C0>.<FF><FF><FF><FF>
  .  0010:  50 7e 00 00 50 7e 00 00 44 35 2b c3 aa 90 01 00  P~..P~..D5+<C3><AA>...
  .  0020:  01 00 00 00 00 00 00 00                          ........

  440538069939524 0x480 [0x28]: PERF_RECORD_SAMPLE(IP, 0x4001): 32336/32336: 0xffffffff88c00b27 period: 1 addr: 0
   ... thread: sleep:32336
   ...... dso: <not found>

  0x4a8 [0x28]: event: 9
  . ... raw event: size 40 bytes
  .  0000:  09 00 00 00 01 40 28 00 27 0b c0 88 ff ff ff ff  .....@(.'.<C0>.<FF><FF><FF><FF>
  .  0010:  50 7e 00 00 50 7e 00 00 90 4a 2b c3 aa 90 01 00  P~..P~...J+<C3><AA>...
  .  0020:  01 00 00 00 00 00 00 00                          ........

  440538069944976 0x4a8 [0x28]: PERF_RECORD_SAMPLE(IP, 0x4001): 32336/32336: 0xffffffff88c00b27 period: 1 addr: 0

  $ pahole --seek_bytes=0x420 -C 'perf_event_header(sizeof=size,type=type,type_enum=perf_event_type)' --count 3 ~/bin/perf < perf.data
  {
  	.header = 0x0a 0x00 0x00 0x00 0x02 0x00 0x60 0x00,
  	.pid = 0x7e50,
  	.tid = 0x7e50,
  	.start = 0x7fffd8b69000,
  	.len = 0x2000,
  	.pgoff = 0,
  	.maj = 0,
  	.min = 0,
  	.ino = 0,
  	.ino_generation = 0,
  	.prot = 0x5,
  	.flags = 0x1002,
  	.filename = "[vdso]",
  },
  {
  	.header = 0x09 0x00 0x00 0x00 0x01 0x40 0x28 0x00,
  	.array = { 0xffffffff88c00b27, 0x7e5000007e50, 0x190aac32b3544, 0x1 },
  },
  {
  	.header = 0x09 0x00 0x00 0x00 0x01 0x40 0x28 0x00,
  	.array = { 0xffffffff88c00b27, 0x7e5000007e50, 0x190aac32b4a90, 0x1 },
  },
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo ff7815a0f8 pahole: Add missing space before '}' in array__fprintf_base_type_value()
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 5f2502274e pahole: Support zero sized arrays in array__fprintf_base_type_value()
We still need to support it in the array__fprintf_base_type_value()
caller, in the next patch.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 3aadfbdd72 pahole: Follow array type typedefs to find real sizeof(entry)
We follow typedefs to decide when to call
array__fprintf_base_type_value(), but then we were not following when
looking for the sizeof of its entries, fix it.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 7309039aa7 pahole: Make 'type' + 'type_enum' select a type to cast a variable sized record
There is this usecase where a header member selects how to interpret the
bytes after the header as some other type, and when this is coupled with
an enum that have as its entries the names of the structs that decode
thsoe types, we should take advantage of it, for sure.

That is the case with, hopefully, many on-disk formats, and probably
even with things that never touch disks.

It is mostly the case with perf.data files, where we have as the fixed
header part this, and since it is a kernel ABI, lets remember that Linux
kernels comes with BTF for all its types, right? Ok, so lets use the
super concise form:

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

See that 'type' field? Now it is as interesting as that 'size' one
(remember, that is what says how really sized is a record), so, I know
that in perf land, that type is associated with this enum:

  $ pahole 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_MAX = 20,
  };
  $

See? Now lets try to see if the perf developers used some sensible
naming for the structs representing the payload associated with those
perf_event_header types, and now we need to use whatever debuginfo is in
the perf tool binary when built with -g, which is DWARF, since the
kernel was not so nice and didn't provide types for those records:

  $ pahole 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_MAX = 20,
  };
  $ pahole ~/bin/perf -C perf_record_mmap
  struct perf_record_mmap {
  	struct perf_event_header   header;               /*     0     8 */
  	__u32                      pid;                  /*     8     4 */
  	__u32                      tid;                  /*    12     4 */
  	__u64                      start;                /*    16     8 */
  	__u64                      len;                  /*    24     8 */
  	__u64                      pgoff;                /*    32     8 */
  	char                       filename[4096];       /*    40  4096 */

  	/* size: 4136, cachelines: 65, members: 7 */
  	/* last cacheline: 40 bytes */
  };
  $ pahole ~/bin/perf -C perf_record_lost
  struct perf_record_lost {
  	struct perf_event_header   header;               /*     0     8 */
  	__u64                      id;                   /*     8     8 */
  	__u64                      lost;                 /*    16     8 */

  	/* size: 24, cachelines: 1, members: 3 */
  	/* last cacheline: 24 bytes */
  };
  $ pahole ~/bin/perf -C perf_record_comm
  struct perf_record_comm {
  	struct perf_event_header   header;               /*     0     8 */
  	__u32                      pid;                  /*     8     4 */
  	__u32                      tid;                  /*    12     4 */
  	char                       comm[16];             /*    16    16 */

  	/* size: 32, cachelines: 1, members: 4 */
  	/* last cacheline: 32 bytes */
  };
  $ pahole ~/bin/perf -C perf_record_exit
  $ pahole ~/bin/perf -C perf_record_throttle
  struct perf_record_throttle {
  	struct perf_event_header   header;               /*     0     8 */
  	__u64                      time;                 /*     8     8 */
  	__u64                      id;                   /*    16     8 */
  	__u64                      stream_id;            /*    24     8 */

  	/* size: 32, cachelines: 1, members: 4 */
  	/* last cacheline: 32 bytes */
  };
  $ pahole ~/bin/perf -C perf_record_unthrottle
  $ pahole ~/bin/perf -C perf_record_fork
  struct perf_record_fork {
  	struct perf_event_header   header;               /*     0     8 */
  	__u32                      pid;                  /*     8     4 */
  	__u32                      ppid;                 /*    12     4 */
  	__u32                      tid;                  /*    16     4 */
  	__u32                      ptid;                 /*    20     4 */
  	__u64                      time;                 /*    24     8 */

  	/* size: 32, cachelines: 1, members: 6 */
  	/* last cacheline: 32 bytes */
  };
  $ pahole ~/bin/perf -C perf_record_exec
  $ pahole ~/bin/perf -C perf_record_read
  struct perf_record_read {
  	struct perf_event_header   header;               /*     0     8 */
  	__u32                      pid;                  /*     8     4 */
  	__u32                      tid;                  /*    12     4 */
  	__u64                      value;                /*    16     8 */
  	__u64                      time_enabled;         /*    24     8 */
  	__u64                      time_running;         /*    32     8 */
  	__u64                      id;                   /*    40     8 */

  	/* size: 48, cachelines: 1, members: 7 */
  	/* last cacheline: 48 bytes */
  };
  $ pahole ~/bin/perf -C perf_record_sample
  struct perf_record_sample {
  	struct perf_event_header   header;               /*     0     8 */
  	__u64                      array[];              /*     8     0 */

  	/* size: 8, cachelines: 1, members: 2 */
  	/* last cacheline: 8 bytes */
  };
  $ pahole ~/bin/perf -C perf_record_mmap2
  struct perf_record_mmap2 {
  	struct perf_event_header   header;               /*     0     8 */
  	__u32                      pid;                  /*     8     4 */
  	__u32                      tid;                  /*    12     4 */
  	__u64                      start;                /*    16     8 */
  	__u64                      len;                  /*    24     8 */
  	__u64                      pgoff;                /*    32     8 */
  	__u32                      maj;                  /*    40     4 */
  	__u32                      min;                  /*    44     4 */
  	__u64                      ino;                  /*    48     8 */
  	__u64                      ino_generation;       /*    56     8 */
  	/* --- cacheline 1 boundary (64 bytes) --- */
  	__u32                      prot;                 /*    64     4 */
  	__u32                      flags;                /*    68     4 */
  	char                       filename[4096];       /*    72  4096 */

  	/* size: 4168, cachelines: 66, members: 13 */
  	/* last cacheline: 8 bytes */
  };
  $ pahole ~/bin/perf -C perf_record_aux
  struct perf_record_aux {
  	struct perf_event_header   header;               /*     0     8 */
  	__u64                      aux_offset;           /*     8     8 */
  	__u64                      aux_size;             /*    16     8 */
  	__u64                      flags;                /*    24     8 */

  	/* size: 32, cachelines: 1, members: 4 */
  	/* last cacheline: 32 bytes */
  };
  $ pahole ~/bin/perf -C perf_record_itrace_start
  struct perf_record_itrace_start {
  	struct perf_event_header   header;               /*     0     8 */
  	__u32                      pid;                  /*     8     4 */
  	__u32                      tid;                  /*    12     4 */

  	/* size: 16, cachelines: 1, members: 3 */
  	/* last cacheline: 16 bytes */
  };
  $ pahole ~/bin/perf -C perf_record_lost_samples
  struct perf_record_lost_samples {
  	struct perf_event_header   header;               /*     0     8 */
  	__u64                      lost;                 /*     8     8 */

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

And so on. So most can be obtained this way, i.e. casts based on a type
selector present on the common part.

  $ pahole ~/bin/perf --seek_bytes=0x130 -C 'perf_event_header(sizeof=size,type=type,type_enum=perf_event_type)' --count 26 < perf.data
  {
  	.type = 0x4f,
  	.misc = 0,
  	.size = 0x20,
  },
  {
  	.type = 0x49,
  	.misc = 0,
  	.size = 0x28,
  },
  {
  	.type = 0x4a,
  	.misc = 0,
  	.size = 0x20,
  },
  {
  	.header = 0x13 0x00 0x00 0x00 0x00 0x00 0x28 0x00,
  	.id = 0x1,
  	.path = "/",
  },
  {
  	.header = 0x13 0x00 0x00 0x00 0x00 0x00 0x30 0x00,
  	.id = 0x611,
  	.path = "/system.slice",
  },
  {
  	.header = 0x13 0x00 0x00 0x00 0x00 0x00 0x30 0x00,
  	.id = 0x8,
  	.path = "/machine.slice",
  },
  {
  	.header = 0x13 0x00 0x00 0x00 0x00 0x00 0x80 0x00,
  	.id = 0x1e94,
  	.path = "/machine.slice/libpod-42be8e8d4eb9d22405845005f0d04ea398548dccc934a150fbaa3c1f1f9492c2.scope",
  },
  {
  	.header = 0x13 0x00 0x00 0x00 0x00 0x00 0x58 0x00,
  	.id = 0xd,
  	.path = "/machine.slice/machine-qemu\x2d1\x2drhel6.sandy.scope",
  },
  {
  	.header = 0x03 0x00 0x00 0x00 0x00 0x00 0x28 0x00,
  	.pid = 0x7e50,
  	.tid = 0x7e50,
  	.comm = "perf",
  },
  {
  	.header = 0x03 0x00 0x00 0x00 0x00 0x20 0x28 0x00,
  	.pid = 0x7e50,
  	.tid = 0x7e50,
  	.comm = "sleep",
  },
  {
  	.header = 0x0a 0x00 0x00 0x00 0x02 0x00 0x68 0x00,
  	.pid = 0x7e50,
  	.tid = 0x7e50,
  	.start = 0x55ea2a865000,
  	.len = 0x4000,
  	.pgoff = 0x2000,
  	.maj = 0xfd,
  	.min = 0,
  	.ino = 0x1e0526,
  	.ino_generation = 0xc97273c3,
  	.prot = 0x5,
  	.flags = 0x1802,
  	.filename = "/usr/bin/sleep",
  },
  {
  	.header = 0x0a 0x00 0x00 0x00 0x02 0x00 0x70 0x00,
  	.pid = 0x7e50,
  	.tid = 0x7e50,
  	.start = 0x7f53040c7000,
  	.len = 0x20000,
  	.pgoff = 0x1000,
  	.maj = 0xfd,
  	.min = 0,
  	.ino = 0x1e1faf,
  	.ino_generation = 0x83ee2ed3,
  	.prot = 0x5,
  	.flags = 0x1802,
  	.filename = "/usr/lib64/ld-2.29.so",
  },
  {
  	.header = 0x0a 0x00 0x00 0x00 0x02 0x00 0x60 0x00,
  	.pid = 0x7e50,
  	.tid = 0x7e50,
  	.start = 0x7fffd8b69000,
  	.len = 0x2000,
  	.pgoff = 0,
  	.maj = 0,
  	.min = 0,
  	.ino = 0,
  	.ino_generation = 0,
  	.prot = 0x5,
  	.flags = 0x1002,
  	.filename = "[vdso]",
  },
  {
  	.header = 0x09 0x00 0x00 0x00 0x01 0x40 0x28 0x00,
  	.array = { },
  },
  {
  	.header = 0x09 0x00 0x00 0x00 0x01 0x40 0x28 0x00,
  	.array = { },
  },
  {
  	.header = 0x09 0x00 0x00 0x00 0x01 0x40 0x28 0x00,
  	.array = { },
  },
  {
  	.header = 0x09 0x00 0x00 0x00 0x01 0x40 0x28 0x00,
  	.array = { },
  },
  {
  	.header = 0x09 0x00 0x00 0x00 0x01 0x40 0x28 0x00,
  	.array = { },
  },
  {
  	.header = 0x09 0x00 0x00 0x00 0x01 0x40 0x28 0x00,
  	.array = { },
  },
  {
  	.header = 0x09 0x00 0x00 0x00 0x02 0x40 0x28 0x00,
  	.array = { },
  },
  {
  	.header = 0x09 0x00 0x00 0x00 0x02 0x40 0x28 0x00,
  	.array = { },
  },
  {
  	.header = 0x0a 0x00 0x00 0x00 0x02 0x00 0x70 0x00,
  	.pid = 0x7e50,
  	.tid = 0x7e50,
  	.start = 0x7f5303efe000,
  	.len = 0x14d000,
  	.pgoff = 0x22000,
  	.maj = 0xfd,
  	.min = 0,
  	.ino = 0x1e028a,
  	.ino_generation = 0xd5947787,
  	.prot = 0x5,
  	.flags = 0x1002,
  	.filename = "/usr/lib64/libc-2.29.so",
  },
  {
  	.header = 0x09 0x00 0x00 0x00 0x02 0x40 0x28 0x00,
  	.array = { },
  },
  {
  	.header = 0x09 0x00 0x00 0x00 0x02 0x40 0x28 0x00,
  	.array = { },
  },
  {
  	.type = PERF_RECORD_EXIT,
  	.misc = 0,
  	.size = 0x30,
  },
  {
  	.type = 0x44,
  	.misc = 0,
  	.size = 0x8,
  },
  $

So now we go and get the whole thing in this command line:

Ok, we lost some stuff along the way, namely we need to do recursive pretty
printing, the .header field is being now defaulted to the primitive hex dumper
that is the last resort when pahole wasn't instructed to dtrt...

Tomorrow, probably :-)

But I'll point this to global kernel variables, that now we know the types,
--expand_pointers is there for just showing the structure, with support for
files, in addition to reading from stdin, we'll be able to get things from
random places, not just sequential, etc.

Addictive :-\

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 42b7a759f3 dutil: Add a strlwr() helper to lowercase a string, returning it
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo a5bb31b86f pahole: Fix --skip for variable sized records
We were not honouring 'sizeof=size' with --skip.

Before:

  $ pahole --seek_bytes=0x130 'perf_event_header(sizeof=size,type=type,type_enum=perf_event_type)' --count 5 < perf.data
  {
  	.type = 0x4f,
  	.misc = 0,
  	.size = 0x20,
  },
  {
  	.type = 0x49,
  	.misc = 0,
  	.size = 0x28,
  },
  {
  	.type = 0x4a,
  	.misc = 0,
  	.size = 0x20,
  },
  {
  	.type = PERF_RECORD_CGROUP,
  	.misc = 0,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_CGROUP,
  	.misc = 0,
  	.size = 0x30,
  },
  $ pahole --seek_bytes=0x130 'perf_event_header(sizeof=size,type=type,type_enum=perf_event_type)' --count 2 --skip 3 < perf.data
  {
  	.type = 0xcf8532e,
  	.misc = 0xffffffffffff8c52,
  	.size = 0x1,
  },
  {
  	.type = 0x49,
  	.misc = 0,
  	.size = 0x28,
  },

After:

  $ pahole --seek_bytes=0x130 'perf_event_header(sizeof=size,type=type,type_enum=perf_event_type)' --count 2 --skip 3 < perf.data
  {
  	.type = PERF_RECORD_CGROUP,
  	.misc = 0,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_CGROUP,
  	.misc = 0,
  	.size = 0x30,
  },
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo f4df384d77 pahole: Decouple reading ->sizeof_member from printing
We need to know it right after reading the fixed part, so that we can
fix the --skip handling.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 78cdde5cb7 pahole: Introduce 'type_enum' class argument
This, together with the 'type=member' allows for associating an enum to the
'type' member, which initially allows for looking up the value in the 'type'
member in the 'type_enum' to pretty print it, e.g.:

Hey, it is kernel ABI, so lets get it from BTF, way faster, and this way we can
test if all the enumerations, etc are readily available in the kernel BTF file,
and indeed they are :-)

Back to the pretty printing:

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

Check if that enum is there:

  $ pahole --seek_bytes=0x130 'perf_event_header(sizeof=size,type=type,type_enum=bla)' --count 26 < perf.data
  pahole: the type enum 'bla' wasn't found in '/sys/kernel/btf/vmlinux'
  $

Use the correct enumeration (enum perf_event_type):

  $ pahole --seek_bytes=0x130 'perf_event_header(sizeof=size,type=type,type_enum=perf_event_type)' --count 26 < perf.data
  {
  	.type = 0x4f,
  	.misc = 0,
  	.size = 0x20,
  },
  {
  	.type = 0x49,
  	.misc = 0,
  	.size = 0x28,
  },
  {
  	.type = 0x4a,
  	.misc = 0,
  	.size = 0x20,
  },
  {
  	.type = PERF_RECORD_CGROUP,
  	.misc = 0,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_CGROUP,
  	.misc = 0,
  	.size = 0x30,
  },
  {
  	.type = PERF_RECORD_CGROUP,
  	.misc = 0,
  	.size = 0x30,
  },
  {
  	.type = PERF_RECORD_CGROUP,
  	.misc = 0,
  	.size = 0x80,
  },
  {
  	.type = PERF_RECORD_CGROUP,
  	.misc = 0,
  	.size = 0x58,
  },
  {
  	.type = PERF_RECORD_COMM,
  	.misc = 0,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_COMM,
  	.misc = 0x2000,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_MMAP2,
  	.misc = 0x2,
  	.size = 0x68,
  },
  {
  	.type = PERF_RECORD_MMAP2,
  	.misc = 0x2,
  	.size = 0x70,
  },
  {
  	.type = PERF_RECORD_MMAP2,
  	.misc = 0x2,
  	.size = 0x60,
  },
  {
  	.type = PERF_RECORD_SAMPLE,
  	.misc = 0x4001,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_SAMPLE,
  	.misc = 0x4001,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_SAMPLE,
  	.misc = 0x4001,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_SAMPLE,
  	.misc = 0x4001,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_SAMPLE,
  	.misc = 0x4001,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_SAMPLE,
  	.misc = 0x4001,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_SAMPLE,
  	.misc = 0x4002,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_SAMPLE,
  	.misc = 0x4002,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_MMAP2,
  	.misc = 0x2,
  	.size = 0x70,
  },
  {
  	.type = PERF_RECORD_SAMPLE,
  	.misc = 0x4002,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_SAMPLE,
  	.misc = 0x4002,
  	.size = 0x28,
  },
  {
  	.type = PERF_RECORD_EXIT,
  	.misc = 0,
  	.size = 0x30,
  },
  {
  	.type = 0x44,
  	.misc = 0,
  	.size = 0x8,
  },
  $

But the coolest part comes next, when we'll lookup the enumerator, say,
PERF_RECORD_MMAP2, to find a type to pretty print what comes after the common
header fields, i.e.:

Ok, kernel BTF doesn't contains 'struct perf_record_mmap2', so back to using
perf's DWARF info :-)

  $ pahole -C perf_record_mmap2 ~/bin/perf
  struct perf_record_mmap2 {
  	struct perf_event_header   header;               /*     0     8 */
  	__u32                      pid;                  /*     8     4 */
  	__u32                      tid;                  /*    12     4 */
  	__u64                      start;                /*    16     8 */
  	__u64                      len;                  /*    24     8 */
  	__u64                      pgoff;                /*    32     8 */
  	__u32                      maj;                  /*    40     4 */
  	__u32                      min;                  /*    44     4 */
  	__u64                      ino;                  /*    48     8 */
  	__u64                      ino_generation;       /*    56     8 */
  	/* --- cacheline 1 boundary (64 bytes) --- */
  	__u32                      prot;                 /*    64     4 */
  	__u32                      flags;                /*    68     4 */
  	char                       filename[4096];       /*    72  4096 */

  	/* size: 4168, cachelines: 66, members: 13 */
  	/* last cacheline: 8 bytes */
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 163c330d31 dwarves: Introduce cu__find_enumeration_by_name()
We'll use it in an upcoming feature, to pretty print fields that albeit
not declared as an enum, have values coming from one.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 20051b7157 pahole: Add the 'type' modifier to make a struct member be used to find a cast type
This is the first step:

  $ pahole -V -C 'perf_event_header(sizeof=size,type=type)' ~/bin/perf
  pahole: sizeof_operator for 'perf_event_header' is 'size'
  pahole: type member for 'perf_event_header' is 'type'
  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 */
  };
  $

Next step is to add another modifier that will point to an enum that
maps the value in perf_event_header->type to a string that can then be
used to lookup the type to be used to pretty print what is after
'sizeof(struct perf_event_header)', i.e. things like:

  $ pahole -EC perf_record_mmap ~/bin/perf
  struct perf_record_mmap {
  	struct perf_event_header {
  		/* typedef __u32 */ unsigned int       type;     /*     0     4 */
  		/* typedef __u16 */ short unsigned int misc;     /*     4     2 */
  		/* typedef __u16 */ short unsigned int size;     /*     6     2 */
  	} header; /*     0     8 */
  	/* typedef __u32 */ unsigned int               pid;      /*     8     4 */
  	/* typedef __u32 */ unsigned int               tid;      /*    12     4 */
  	/* typedef __u64 */ long long unsigned int     start;    /*    16     8 */
  	/* typedef __u64 */ long long unsigned int     len;      /*    24     8 */
  	/* typedef __u64 */ long long unsigned int     pgoff;    /*    32     8 */
  	char                       filename[4096];               /*    40  4096 */

  	/* size: 4136, cachelines: 65, members: 7 */
  	/* last cacheline: 40 bytes */
  };
  $

The various validations performed:

  $ pahole -V -C 'perf_event_header(sizeof=size,typ=type)' ~/bin/perf
  pahole: sizeof_operator for 'perf_event_header' is 'size'
  pahole: invalid arg 'typ' in 'perf_event_header(sizeof=size,typ=type)' (known args: sizeof=member, type=member)
  $
  $ pahole -V -C 'perf_event_header(sizeof=size,type=bla)' ~/bin/perf
  pahole: sizeof_operator for 'perf_event_header' is 'size'
  pahole: type member for 'perf_event_header' is 'bla'
  pahole: the type member 'bla' wasn't found in the 'perf_event_header' type
  $
  $ pahole -V -C 'perf_event_header(sizeof=size,type=type)' ~/bin/perf
  pahole: sizeof_operator for 'perf_event_header' is 'size'
  pahole: type member for 'perf_event_header' is 'type'
  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 */
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 210dffe0d1 pahole: Iterate classes in the order specified in the command line:
Before we were using the rbtree and then we were traversing in
alphabetical order, not in the command line order, fix that.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 37a5c7c5ba strlist: Allow iterating a strlist in the original order
I.e. when we do:

	pahole -C a,b,c,d binary

We want that the 'a' type be processed first, etc. So add a list for
that.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 6b5d938d99 pahole: Support multiple class/struct args
I.e.:

  $ pahole -C 'perf_event_header(sizeof=siz),a' ~/bin/perf
  pahole: the sizeof member 'siz' not found in the 'perf_event_header' type
  $ pahole -C 'perf_event_header(sizeof=size,b),a' ~/bin/perf
  pahole: invalid, missing '=' in 'perf_event_header(sizeof=size,b)'
  $ pahole -C 'perf_event_header(sizeof=size,b=c),a' ~/bin/perf
  pahole: invalid arg 'b' in 'perf_event_header(sizeof=size,b=c)' (known args: sizeof=member)
  $ pahole -C 'perf_event_header(sizeof=size),a' ~/bin/perf
  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 */
  };
  $

We're for now considering just the first class in that list, so the 'a'
is parsed but not validated, its there just to test the comma as a
separator of class arguments and also as the separator of multiple
classes.

I.e.:

  $ pahole -V -C 'perf_event_header(sizeof=size),a(sizeof=1)' ~/bin/perf
  pahole: sizeof_operator for 'a' is '1'
  pahole: sizeof_operator for 'perf_event_header' is 'size'
  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 */
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo affbebf04b pahole: Make the class splitter take into account per-class parameters
I.e. this is now supported:

  $ pahole -V -C 'perf_event_header(sizeof=size,b),a' ~/bin/perf
  pahole: sizeof_operator for 'perf_event_header' is 'size,b'
  pahole: the sizeof member 'size,b' not found in the 'perf_event_header' type
  $

Now its up to the class args parser to split its parameters, i.e. make
'size' be the value of 'sizeof' and then consider 'a', then the 'b'
class will be considered and so on.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 84387de4a5 pahole: Allow specifying a struct member based sizeof() override
When we deal with things like:

  $ 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 */
  };
  $

Records are put on a perf.data file with size specifying that the next
record is at:

	 perf_event_header->size - sizeof(struct perf_event_header)

after the current record, so allow for that with the following syntax:

	$ pahole -C 'perf_event_header(sizeof=size)' ~/bin/perf < perf.data

I.e. pahole should go on reading from stdin 'struct perf_event_header'
records that use that 'size' field to figure out where the next header
is.

E.g.:

Having:

  $ perf report -D | head
  # To display the perf.data header info, please use --header/--header-only options.
  #

  0x130 [0x20]: event: 79
  .
  . ... raw event: size 32 bytes
  .  0000:  4f 00 00 00 00 00 20 00 1f 00 00 00 00 00 00 00  O..... .........
  .  0010:  31 30 9b 3c 00 00 00 00 2e 53 f8 0c 52 8c 01 00  10.<.....S�.R...

  0 0x130 [0x20]: PERF_RECORD_TIME_CONV: unhandled!
  $

We see that the first record is at offset 0x130, furthermore:

  $ perf report -D | grep "Aggregated stats:" -A 1
  Aggregated stats:
             TOTAL events:         26
  $

So we have 26 events, so lets use --seek_bytes to start reading from the
offset for the first event and ask for those 26 events to be decoded,
and adding the decimal representation for the type, so that we can match
it up with 'perf report -D' output, we see:

  $ pahole --seek_bytes=0x130 -C 'perf_event_header(sizeof=size)' --count 26 ~/bin/perf < perf.data
  {
  	.type = 0x4f (79),
  	.misc = 0 (0),
  	.size = 0x20 (32),
  },
  {
  	.type = 0x49 (73),
  	.misc = 0 (0),
  	.size = 0x28 (40),
  },
  {
  	.type = 0x4a (74),
  	.misc = 0 (0),
  	.size = 0x20 (32),
  },
  {
  	.type = 0x13 (19),
  	.misc = 0 (0),
  	.size = 0x28 (40),
  },
  {
  	.type = 0x13 (19),
  	.misc = 0 (0),
  	.size = 0x30 (48),
  },
  {
  	.type = 0x13 (19),
  	.misc = 0 (0),
  	.size = 0x30 (48),
  },
  {
  	.type = 0x13 (19),
  	.misc = 0 (0),
  	.size = 0x80 (128),
  },
  {
  	.type = 0x13 (19),
  	.misc = 0 (0),
  	.size = 0x58 (88),
  },
  {
  	.type = 0x3 (3),
  	.misc = 0 (0),
  	.size = 0x28 (40),
  },
  {
  	.type = 0x3 (3),
  	.misc = 0x2000 (8192),
  	.size = 0x28 (40),
  },
  {
  	.type = 0xa (10),
  	.misc = 0x2 (2),
  	.size = 0x68 (104),
  },
  {
  	.type = 0xa (10),
  	.misc = 0x2 (2),
  	.size = 0x70 (112),
  },
  {
  	.type = 0xa (10),
  	.misc = 0x2 (2),
  	.size = 0x60 (96),
  },
  {
  	.type = 0x9 (9),
  	.misc = 0x4001 (16385),
  	.size = 0x28 (40),
  },
  {
  	.type = 0x9 (9),
  	.misc = 0x4001 (16385),
  	.size = 0x28 (40),
  },
  {
  	.type = 0x9 (9),
  	.misc = 0x4001 (16385),
  	.size = 0x28 (40),
  },
  {
  	.type = 0x9 (9),
  	.misc = 0x4001 (16385),
  	.size = 0x28 (40),
  },
  {
  	.type = 0x9 (9),
  	.misc = 0x4001 (16385),
  	.size = 0x28 (40),
  },
  {
  	.type = 0x9 (9),
  	.misc = 0x4001 (16385),
  	.size = 0x28 (40),
  },
  {
  	.type = 0x9 (9),
  	.misc = 0x4002 (16386),
  	.size = 0x28 (40),
  },
  {
  	.type = 0x9 (9),
  	.misc = 0x4002 (16386),
  	.size = 0x28 (40),
  },
  {
  	.type = 0xa (10),
  	.misc = 0x2 (2),
  	.size = 0x70 (112),
  },
  {
  	.type = 0x9 (9),
  	.misc = 0x4002 (16386),
  	.size = 0x28 (40),
  },
  {
  	.type = 0x9 (9),
  	.misc = 0x4002 (16386),
  	.size = 0x28 (40),
  },
  {
  	.type = 0x4 (4),
  	.misc = 0 (0),
  	.size = 0x30 (48),
  },
  {
  	.type = 0x44 (68),
  	.misc = 0 (0),
  	.size = 0x8 (8),
  },

Which matches the output from 'perf report -D':

  $ perf report -D | grep ^0x
  0x130 [0x20]: event: 79
  0x150 [0x28]: event: 73
  0x178 [0x20]: event: 74
  0x198 [0x28]: event: 19
  0x1c0 [0x30]: event: 19
  0x1f0 [0x30]: event: 19
  0x220 [0x80]: event: 19
  0x2a0 [0x58]: event: 19
  0x2f8 [0x28]: event: 3
  0x6b0 [0x8]: event: 68
  0x320 [0x28]: event: 3
  0x348 [0x68]: event: 10
  0x3b0 [0x70]: event: 10
  0x420 [0x60]: event: 10
  0x480 [0x28]: event: 9
  0x4a8 [0x28]: event: 9
  0x4d0 [0x28]: event: 9
  0x4f8 [0x28]: event: 9
  0x520 [0x28]: event: 9
  0x548 [0x28]: event: 9
  0x570 [0x28]: event: 9
  0x598 [0x28]: event: 9
  0x5c0 [0x70]: event: 10
  0x630 [0x28]: event: 9
  0x658 [0x28]: event: 9
  0x680 [0x30]: event: 4
  $

There is only one "reordering" as pahole is decoding this in the on-disk
order, while 'perf report -D' knows about the timestamps encoded as perf
those events perf_event_attr->sample_type and orders those events before
printing.

So we're on our way to a universal type (BTF, CTF, DWARF, others)
dumper, now I need a name for this tool, 'spretty' comes to mind, but,
humm, the urban dict seems to know about that already ;-\

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo e0773683fa dwarves: Allow setting a struct/class member as the source of sizeof()
This one just allows that to be set, i.e.:

  $ pahole -C perf_event_header ~/bin/perf
  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 */
  };
  $ pahole -C 'perf_event_header(sizeof=size)' --seek_bytes=0x348 --count 1 ~/bin/perf < perf.data
  {
  	.type = 0xa,
  	.misc = 0x2,
  	.size = 0x68,
  },
  $

But:

  $ pahole -C 'perf_event_header(sizeof=bla)' --seek_bytes=0x348 --count 1 ~/bin/perf < perf.data
  pahole: the sizeof member 'bla' not found in the 'perf_event_header' type
  $

And:

  $ pahole -C 'perf_event_header(size=misc)' --seek_bytes=0x348 --count 1 ~/bin/perf < perf.data
  pahole: invalid arg 'size' in 'perf_event_header(size=misc)' (known args: sizeof=member)
  $

The next cset will implement sizeof(type) with that modifier, using the
stdin bytes to obtain the size (0x68) in the above case, and then we'll
be able to print a sequence of variable-sized records correctly.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo f399db09a0 pahole: Allow simple parser for arguments to classes
For now we need the simplest parser to specify a field that should be
used as the sizeof operator in structs that have a header for a variable
sized record, i.e., perf.data file and its 'struct perf_event_header' +
'struct perf_record_{mmap,comm,exec,etc}':

  $ perf report -D
<SNIP>
  0x348 [0x68]: event: 10
  .
  . ... raw event: size 104 bytes
  .  0000:  0a 00 00 00 02 00 68 00 50 7e 00 00 50 7e 00 00  ......h.P~..P~..
  .  0010:  00 50 86 2a ea 55 00 00 00 40 00 00 00 00 00 00  .P.*<EA>U...@......
  .  0020:  00 20 00 00 00 00 00 00 fd 00 00 00 00 00 00 00  . ......<FD>.......
  .  0030:  26 05 1e 00 00 00 00 00 c3 73 72 c9 00 00 00 00  &.......<C3>sr<C9>....
  .  0040:  05 00 00 00 02 18 00 00 2f 75 73 72 2f 62 69 6e  ......../usr/bin
  .  0050:  2f 73 6c 65 65 70 00 00 50 7e 00 00 50 7e 00 00  /sleep..P~..P~..
  .  0060:  31 2d 2a c3 aa 90 01 00                          1-*<C3><AA>...

  440538069871921 0x348 [0x68]: PERF_RECORD_MMAP2 32336/32336: [0x55ea2a865000(0x4000) @ 0x2000 fd:00 1967398 3379721155]: r-xp /usr/bin/sleep
<SNIP>

  $ pahole -C 'perf_event_header' --seek_bytes 0x348 --count 1 ~/bin/perf < perf.data
  {
  	.type = 0xa,
  	.misc = 0x2,
  	.size = 0x68,
  },
  $

Empty list of args is ok, just chop that off and do the same as above,
without ():

  $ pahole -C 'perf_event_header()' --seek_bytes 0x348 --count 1 ~/bin/perf < perf.data
  {
  	.type = 0xa,
  	.misc = 0x2,
  	.size = 0x68,
  },
  $

Boolean args (without a value) not yet supported:

  $ pahole -C 'perf_event_header(sizeof)' --seek_bytes 0x348 --count 1 ~/bin/perf < perf.data
  pahole: invalid, missing '=' in 'perf_event_header(sizeof)'
  $

A value is required:

  $ pahole -C 'perf_event_header(sizeof=)' --seek_bytes 0x348 --count 1 ~/bin/perf < perf.data
  pahole: invalid, missing value in 'perf_event_header(sizeof=)'
  $

Valid form:

  $ pahole -C 'perf_event_header(sizeof=size)' --seek_bytes 0x348 --count 1 ~/bin/perf < perf.data
  {
  	.type = 0xa,
  	.misc = 0x2,
  	.size = 0x68,
  },
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 04d957ba3c pahole: Add variable for class name when traversing list of classes
We'll have to at this point look for arguments, like a different way of
finding the sizeof for a class, say:

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

In a perf.data file we should consider sizeof(struct perf_event_header)
to really be header->size, o that we can traverse the file one
perf_event_header at a time.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Hao Luo f3d9054ba8 btf_encoder: Teach pahole to store percpu variables in vmlinux BTF.
On SMP systems, the global percpu variables are placed in a special
'.data..percpu' section, which is stored in a segment whose initial
address is set to 0, the addresses of per-CPU variables are relative
positive addresses [1].

This patch extracts these variables from vmlinux and places them with
their type information in BTF. More specifically, when BTF is encoded,
we find the index of the '.data..percpu' section and then traverse the
symbol table to find those global objects which are in this section.
For each of these objects, we push a BTF_KIND_VAR into the types buffer,
and a BTF_VAR_SECINFO into another buffer, percpu_secinfo. When all the
CUs have finished processing, we push a BTF_KIND_DATASEC into the
btfe->types buffer, followed by the percpu_secinfo's content.

In a v5.8-rc3 linux kernel, I was able to extract 288 such variables.
The build time overhead is small and the space overhead is also small.
See testings below.

A found variable can be invalid in two ways:

 - Its name found in elf_sym__name is invalid.
 - Its size identified by elf_sym__size is 0.

In either case, the BTF containing such symbols will be rejected by the
BTF verifier. Normally we should not see such symbols. But if one is
seen during BTF encoding, the encoder will exit with error. An new flag
'-j' (or '--force') is implemented to help testing, which skips the
invalid symbols and force emit a BTF.

Testing:

- vmlinux size has increased by ~12kb.
  Before:
   $ readelf -SW vmlinux | grep BTF
   [25] .BTF              PROGBITS        ffffffff821a905c 13a905c 2d2bf8 00
  After:
   $ pahole -J vmlinux
   $ readelf -SW vmlinux  | grep BTF
   [25] .BTF              PROGBITS        ffffffff821a905c 13a905c 2d5bca 00

- Common global percpu VARs and DATASEC are found in BTF section.
  $ bpftool btf dump file vmlinux | grep runqueues
  [14152] VAR 'runqueues' type_id=13778, linkage=global-alloc

  $ bpftool btf dump file vmlinux | grep 'cpu_stopper'
  [17582] STRUCT 'cpu_stopper' size=72 vlen=5
  [17601] VAR 'cpu_stopper' type_id=17582, linkage=static

  $ bpftool btf dump file vmlinux | grep ' DATASEC '
  [63652] DATASEC '.data..percpu' size=179288 vlen=288

- Tested bpf selftests.

- pahole exits with error if an invalid symbol is seen during encoding,
  make -f Makefile -j 36 -s
  PAHOLE: Error: Found symbol of zero size when encoding btf (sym: 'yyy', cu: 'xxx.c').
  PAHOLE: Error: Use '-j' or '--force_emit' to ignore such symbols and force emit the btf.
  scripts/link-vmlinux.sh: line 137: 2475712 Segmentation fault      LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}

- With the flag '-j' or '--force', the invalid symbols are ignored.

- Further in verbose mode and with '-j' or '--force' set, a warning is generated:
  PAHOLE: Warning: Found symbol of zero size when encoding btf, ignored (sym: 'yyy', cu: 'xxx.c').
  PAHOLE: Warning: Found symbol of invalid name when encoding btf, ignored (sym: 'zzz', cu: 'sss.c').

References:
 [1] https://lwn.net/Articles/531148/

Signed-off-by: Hao Luo <haoluo@google.com>
Tested-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Cc: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Martin KaFai Lau <kafai@fb.com>
Cc: Oleg Rombakh <olegrom@google.com>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 14:51:17 -03:00
Arnaldo Carvalho de Melo fe28422144 pahole: Introduce --seek_bytes
Works with stdio, will work with files where we'll use plain lseek and
allow for pretty printing trailer structs.

E.g.:

  $ objcopy -O binary --only-section=__versions drivers/scsi/sg.ko versions
  $ 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 */
  };
  $ pahole --count 2 -C modversion_info drivers/scsi/sg.ko < versions
  {
  	.crc = 0x8dabd84,
  	.name = "module_layout",
  },
  {
  	.crc = 0x45e4617b,
  	.name = "no_llseek",
  },
  $ pahole --skip 1 --count 1 -C modversion_info drivers/scsi/sg.ko < versions
  {
  	.crc = 0x45e4617b,
  	.name = "no_llseek",
  },

Then the equivalent, skipping sizeof(modversion_info) explicitely:

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

Using a perf.data file generated by 'perf record':

  $ perf report -D | head -18
  # To display the perf.data header info, please use --header/--header-only options.
  #

  0x130 [0x20]: event: 79
  .
  . ... raw event: size 32 bytes
  .  0000:  4f 00 00 00 00 00 20 00 1f 00 00 00 00 00 00 00  O..... .........
  .  0010:  31 30 9b 3c 00 00 00 00 2e 53 f8 0c 52 8c 01 00  10.<.....S�.R...

  0 0x130 [0x20]: PERF_RECORD_TIME_CONV: unhandled!

  0x150 [0x28]: event: 73
  .
  . ... raw event: size 40 bytes
  .  0000:  49 00 00 00 00 00 28 00 01 00 00 00 00 00 00 00  I.....(.........
  .  0010:  50 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 00  P~..............
  .  0020:  00 00 00 00 00 00 00 00                          ........

  $ pahole --seek_bytes 0x130 --count 1 -C perf_event_header < perf.data
  {
  	.type = 0x4f,
  	.misc = 0,
  	.size = 0x20,
  },
  $ printf "0x%x\n" 79
  0x4f
  $ pahole --seek_bytes 0x150 --count 1 -C perf_event_header < perf.data
  {
  	.type = 0x49,
  	.misc = 0,
  	.size = 0x28,
  },
  $ printf "0x%x\n" 73
  0x49
  $

Now to use more complex types, again using perf.data files.

  # perf record -a sleep 1
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 3.834 MB perf.data (31853 samples) ]
  # perf report -D | grep -m1 -B20 PERF_RECORD_BPF
  0x6aa0 [0x58]: event: 17
  .
  . ... raw event: size 88 bytes
  .  0020:  5f 37 62 65 34 39 65 33 39 33 34 61 31 32 35 62  _7be49e3934a125b
  .  0030:  61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  a...............
  .  0040:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  .  0050:  00 00 00 00 00 00 00 00                          ........

  0 0 0x6aa0 [0x58]: PERF_RECORD_KSYMBOL addr ffffffffc03e0e90 len 203 type 1 flags 0x0 name bpf_prog_7be49e3934a125ba

  0x6af8 [0x38]: event: 18
  .
  . ... raw event: size 56 bytes
  .  0000:  12 00 00 00 00 00 38 00 01 00 00 00 11 00 00 00  ......8.........
  .  0020:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  .  0030:  00 00 00 00 00 00 00 00                          ........

  0 0 0x6af8 [0x38]: PERF_RECORD_BPF_EVENT type 1, flags 0, id 17
  Binary file (standard input) matches
  # pahole -C perf_record_bpf_event ~/bin/perf
  struct perf_record_bpf_event {
  	struct perf_event_header   header;               /*     0     8 */
  	__u16                      type;                 /*     8     2 */
  	__u16                      flags;                /*    10     2 */
  	__u32                      id;                   /*    12     4 */
  	__u8                       tag[8];               /*    16     8 */

  	/* size: 24, cachelines: 1, members: 5 */
  	/* last cacheline: 24 bytes */
  };
  # pahole -C perf_record_bpf_event --seek_bytes 0x6af8 --count 1 ~/bin/perf < perf.data
  {
  	.header = 0x12 0x00 0x00 0x00 0x00 0x00 0x38 0x00,
  	.type = 0x1,
  	.flags = 0,
  	.id = 0x11,
  	.tag = { 0, 0, 0, 0, 0, 0, 0, 0},
  },
  # printf "0x%x\n" 18
  0x12
  # pahole -C perf_record_ksymbol ~/bin/perf
  struct perf_record_ksymbol {
  	struct perf_event_header   header;               /*     0     8 */
  	__u64                      addr;                 /*     8     8 */
  	__u32                      len;                  /*    16     4 */
  	__u16                      ksym_type;            /*    20     2 */
  	__u16                      flags;                /*    22     2 */
  	char                       name[256];            /*    24   256 */

  	/* size: 280, cachelines: 5, members: 6 */
  	/* last cacheline: 24 bytes */
  };
  # pahole -C perf_record_ksymbol --seek_bytes 0x6aa0 --count 1 ~/bin/perf < perf.data
  {
  	.header = 0x11 0x00 0x00 0x00 0x00 0x00 0x58 0x00,
  	.addr = 0xffffffffc03e0e90,
  	.len = 0xcb,
  	.ksym_type = 0x1,
  	.flags = 0,
  	.name = "bpf_prog_7be49e3934a125ba",
  },
  # printf "0x%x\n" 17
  0x11
  #

Need to recursively pretty print substructs, but all seems to work with
the simple hexdump.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-07-01 09:25:57 -03:00
Arnaldo Carvalho de Melo 44af7c02b5 pahole: Implement --skip, just like dd
$ objcopy -O binary --only-section=__versions drivers/scsi/sg.ko versions
  $ 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 */
  };
  $ pahole --count 3 -C modversion_info drivers/scsi/sg.ko < 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 < versions
  {
  	.crc = 0x45e4617b,
  	.name = "no_llseek",
  },
  {
  	.crc = 0xa23fae8c,
  	.name = "param_ops_int",
  },
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-07-01 08:36:28 -03:00
Arnaldo Carvalho de Melo 5631fdcea1 pahole: Introduce --count, just like dd's
$ objcopy -O binary --only-section=.altinstructions ~/git/build/v5.7-rc2+/vmlinux .altinstructions
  $ pahole --count 2 alt_instr  < .altinstructions
  {
  	.instr_offset = 0xffffffffffe0e690,
  	.repl_offset = 0x4873,
  	.cpuid = 0x70,
  	.instrlen = 0x5,
  	.replacementlen = 0x5,
  	.padlen = 0,
  },
  {
  	.instr_offset = 0xffffffffffe0e683,
  	.repl_offset = 0x486b,
  	.cpuid = 0x129,
  	.instrlen = 0x5,
  	.replacementlen = 0x5,
  	.padlen = 0,
  },
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-07-01 08:18:42 -03:00
Arnaldo Carvalho de Melo 272bc75024 man-pages: Add information about stdin raw data pretty printing
And an example.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-27 09:40:51 -03:00
Arnaldo Carvalho de Melo 66835f9e19 pahole: Add support for base type arrays
In addition to "char" arrays printed as strings.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-27 09:40:51 -03:00
Arnaldo Carvalho de Melo 1a67d6e700 pahole: Factor out base_type__fprintf_value()
Will be used when printing arrays of those types.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-27 09:40:51 -03:00
Arnaldo Carvalho de Melo 6fb98aa120 pahole: Support char arrays when dumping from stdin
$ 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 -C modversion_info drivers/scsi/sg.ko < versions | head -12
  {
  	.crc = 0x8dabd84,
  	.name = "module_layout",
  },
  {
  	.crc = 0x45e4617b,
  	.name = "no_llseek",
  },
  {
  	.crc = 0xa23fae8c,
  	.name = "param_ops_int",
  },
  $

Tested-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-27 09:40:51 -03:00
Arnaldo Carvalho de Melo a231d00f8d pahole: Print comma at the end of field name + field value
No need to do it in all the if/else branches.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-27 09:40:51 -03:00
Arnaldo Carvalho de Melo 1b2cdda38c dwarves: Introduce tag__is_array()
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-27 09:40:51 -03:00
Arnaldo Carvalho de Melo a83313fb22 pahole: Pretty print base types in structs from stdin
$ objcopy -O binary --only-section=.altinstructions ~/git/build/v5.7-rc2+/vmlinux .altinstructions
  $ ls -la .altinstructions
  -rwxrwxr-x. 1 acme acme 18551 Jun 24 09:09 .altinstructions
  $

Then, since this 'struct alt_instr' hasn't changed, lets use the shorter
form of just stating the struct name, so that pahole will use
/sys/kernel/btf/vmlinux and do all faster and more concisely:

  $ pahole alt_instr
  struct alt_instr {
  	s32                        instr_offset;         /*     0     4 */
  	s32                        repl_offset;          /*     4     4 */
  	u16                        cpuid;                /*     8     2 */
  	u8                         instrlen;             /*    10     1 */
  	u8                         replacementlen;       /*    11     1 */
  	u8                         padlen;               /*    12     1 */

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

And then, lets pretty print the structs, using gcc's designated
initializer syntax:

  $ pahole alt_instr < .altinstructions | head -32
  {
  	.instr_offset = 0xffffffffffe0e690,
  	.repl_offset = 0x4873,
  	.cpuid = 0x70,
  	.instrlen = 0x5,
  	.replacementlen = 0x5,
  	.padlen = 0,
  },
  {
  	.instr_offset = 0xffffffffffe0e683,
  	.repl_offset = 0x486b,
  	.cpuid = 0x129,
  	.instrlen = 0x5,
  	.replacementlen = 0x5,
  	.padlen = 0,
  },
  {
  	.instr_offset = 0xfffffffffec5722a,
  	.repl_offset = 0x4863,
  	.cpuid = 0xeb,
  	.instrlen = 0x2,
  	.replacementlen = 0,
  	.padlen = 0,
  },
  {
  	.instr_offset = 0xfffffffffec57222,
  	.repl_offset = 0x4856,
  	.cpuid = 0x91,
  	.instrlen = 0x5,
  	.replacementlen = 0x5,
  	.padlen = 0x5,
  },
  $

Probably we need to align the =, that is easy, but not strictly needed
at this point.

Suggested-by: Joe Lawrence <joe.lawrence@redhat.com>
Tested-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-27 09:40:45 -03:00
Arnaldo Carvalho de Melo cc65946e30 dwarves: Adopt tag__is_base_type() from ctrace.c
We'll need it in pahole when pretty printing raw data as structs, etc.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-24 14:14:33 -03:00
Arnaldo Carvalho de Melo d8079c6d37 pahole: Hex dump a type from stdio when it isn't a tty
For now the only aspect of the type that is considered is its size, so
one line each sizeof(type) will be hex dumped, e.g.:

  $ objcopy -O binary --only-section=.altinstructions ~/git/build/v5.7-rc2+/vmlinux .altinstructions
  $ ls -la .altinstructions
  -rwxrwxr-x. 1 acme acme 18551 Jun 24 09:09 .altinstructions
  $ pahole -C alt_instr ~/git/build/v5.7-rc2+/vmlinux
  struct alt_instr {
  	s32                        instr_offset;         /*     0     4 */
  	s32                        repl_offset;          /*     4     4 */
  	u16                        cpuid;                /*     8     2 */
  	u8                         instrlen;             /*    10     1 */
  	u8                         replacementlen;       /*    11     1 */
  	u8                         padlen;               /*    12     1 */

  	/* size: 13, cachelines: 1, members: 6 */
  	/* last cacheline: 13 bytes */
  } __attribute__((__packed__));
  $ pahole -C alt_instr ~/git/build/v5.7-rc2+/vmlinux < .altinstructions  | head
  0x90 0xe6 0xe0 0xff 0x73 0x48 0x00 0x00 0x70 0x00 0x05 0x05 0x00,
  0x83 0xe6 0xe0 0xff 0x6b 0x48 0x00 0x00 0x29 0x01 0x05 0x05 0x00,
  0x2a 0x72 0xc5 0xfe 0x63 0x48 0x00 0x00 0xeb 0x00 0x02 0x00 0x00,
  0x22 0x72 0xc5 0xfe 0x56 0x48 0x00 0x00 0x91 0x00 0x05 0x05 0x05,
  0x0c 0x73 0xc5 0xfe 0x4e 0x48 0x00 0x00 0xeb 0x00 0x02 0x00 0x00,
  0x04 0x73 0xc5 0xfe 0x41 0x48 0x00 0x00 0x91 0x00 0x02 0x00 0x00,
  0x72 0x73 0xc5 0xfe 0x34 0x48 0x00 0x00 0xf3 0x00 0x2b 0x2b 0x29,
  0xca 0x73 0xc5 0xfe 0x52 0x48 0x00 0x00 0xec 0x00 0x18 0x18 0x16,
  0xbd 0x73 0xc5 0xfe 0x5d 0x48 0x00 0x00 0xed 0x00 0x18 0x05 0x16,
  0xd3 0x7a 0xc5 0xfe 0x55 0x48 0x00 0x00 0x34 0x01 0x03 0x03 0x03,
  $

Suggested-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-24 14:13:28 -03:00
Arnaldo Carvalho de Melo 38109ab45f spec: Fix date
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-06-12 09:21:52 -03:00
Arnaldo Carvalho de Melo e709afe6a9 dwarves: Prep v1.17
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-03-13 16:36:02 -03:00
Arnaldo Carvalho de Melo f14426e410 docs: Add command line to generate tarball with a prefix
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-03-12 16:55:15 -03:00
Arnaldo Carvalho de Melo 0b2621d426 dwarves: Avoid truncation when concatenating paths for dir entries
To cope with this warning on s390x:

  /usr/bin/cc -DDWARVES_VERSION=\"v1.16\" -D_GNU_SOURCE -Ddwarves_EXPORTS -I/builddir/build/BUILD/dwarves-1.16 -I/builddir/build/BUILD/dwarves-1.16/lib/bpf/include/uapi  -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=zEC12 -mtune=z13 -fasynchronous-unwind-tables -fstack-clash-protection -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Werror -ggdb -O2 -fPIC   -o CMakeFiles/dwarves.dir/libctf.c.o   -c /builddir/build/BUILD/dwarves-1.16/libctf.c
  /builddir/build/BUILD/dwarves-1.16/dwarves.h: In function 'cus__load_dir':
  /builddir/build/BUILD/dwarves-1.16/dwarves.c:1663:44: error: '%s' directive output may be truncated writing up to 255 bytes into a region of size between 0 and 4095 [-Werror=format-truncation=]
   1663 |   snprintf(pathname, sizeof(pathname), "%s/%s",
        |                                            ^~
  In file included from /usr/include/stdio.h:867,
                   from /builddir/build/BUILD/dwarves-1.16/dwarves.c:18:
  /usr/include/bits/stdio2.h:67:10: note: '__builtin___snprintf_chk' output between 2 and 4352 bytes into a destination of size 4096
     67 |   return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
        |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     68 |        __bos (__s), __fmt, __va_arg_pack ());
        |        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /builddir/build/BUILD/dwarves-1.16/dwarves.c:1663:44: error: '%s' directive output may be truncated writing up to 255 bytes into a region of size between 0 and 4095 [-Werror=format-truncation=]
   1663 |   snprintf(pathname, sizeof(pathname), "%s/%s",
        |                                            ^~
  In file included from /usr/include/stdio.h:867,
                   from /builddir/build/BUILD/dwarves-1.16/dwarves.c:18:
  /usr/include/bits/stdio2.h:67:10: note: '__builtin___snprintf_chk' output between 2 and 4352 bytes into a destination of size 4096

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-02-12 16:28:49 -03:00
Arnaldo Carvalho de Melo d7b3510795 dwarves: Don't use conf if its NULL in cus__load_running_kernel()
Don't use it if NULL, fixing a segfault with dtagnames as reported in:

https://bugzilla.redhat.com/show_bug.cgi?id=1795379

Reported-by: Jan Pokorný <jpokorny@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-02-12 16:10:09 -03:00
Arnaldo Carvalho de Melo dde3eb086d dwarves: Make list__for_all_tags() more robust
Return if passed a zeroed list or an empty one.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-02-12 16:04:31 -03:00
Andrii Nakryiko 081f3618a7 dwarves: Add -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 to build libbpf
We need that as the fix in upstream libbpf is in the
tools/lib/bpf/Makefile, that isn't used when building libbpf as part of
pahole, see:

  "Makefile: back-port _FILE_OFFSET_BITS=64 and _LARGEFILE64_SOURCE to Makefile"
  4a50ceb043

That refers to this in the kernel sources:

  71dd77fd4bf7 ("libbpf: use LFS (_FILE_OFFSET_BITS) instead of direct mmap2 syscall")

Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Julia Kartseva <hex@fb.com>
Cc: Yonghong Song <yhs@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-02-03 08:52:26 +01:00
Arnaldo Carvalho de Melo e8f43a4963 libbpf: Get latest libbpf
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-02-03 08:43:10 +01:00
Jason A. Donenfeld de84ae36c7 cmake: libebl was merged into libdw
Since elfutils 178, libebl is now part of libdw, so searching for libebl
always fails. Simply remove it from the search.

Reviewer notes:

I even built dwarves with the patch against and old elfutils-0.176 and a
new elfutils-0.178 to double check. Builds fine with both.

With elfutils-0.178 pahole even automagically works with the new
debuginfo-client support.  See

https://sourceware.org/elfutils/Debuginfod.html

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Mark Wielaard <mark@klomp.org>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-02-03 08:42:13 +01:00
Arnaldo Carvalho de Melo 290b8fdbda pahole: Improve --contains --recursive a bit
Its not yet correct, misses cases where a top level struct doesn't have
the contained type but some of its substructs have, i.e. right now it
looks if the top level struct has the looked up container type and if it
has, it prints its name and then goes to look at all its members if some
has the looked up container type, recursively.

It should go all the way down, even when a struct doesn't have the
looked up contained type some of its members may have.

So for now its better to use 'pahole -E struct_name | less' and then
search for the type, will be fixed after DevConf.cz 2020 :-)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-21 12:34:42 -03:00
Arnaldo Carvalho de Melo 3d5be866e5 pahole: Fill 'tab' with spaces earlier
We need it in --recursive --contains, otherwise we don't ident.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-21 12:32:12 -03:00
Petr Vandrovec 88674f0395 gobuffer: Do not crash on object without any public symbols
pahole -J .tmp_linux.btf during Linux build process always crashes
on my system.

Problem is that when gobuffer is initialized via gobuffer__init(),
it is in state where 'index' (AKA its size) is set to 1, but
'entries' is NULL.

State corrects itself if 'gobuffer__add()' is invoked, as that
will allocate buffer (even if added len == 0).  But if __add()
is never invoked because only anonymous symbols are present,
one ends up with gobuffer that crashes gobuffer__copy.

Instead of allocating single-byte buffer always I opted for
checking if gobuffer entries is NULL before use in copy and
compress - gobuffer__init() would need prototype change to
report malloc failures, and it seems unnecessary to allocate
memory always - even if file does not have any symbols after
all.

(gdb) bt
 #0  __memmove_sse2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:287
 #1  0x00007f2f2c1ec2ee in btf_elf__encode (btfe=0x5654e31e2e30, flags=flags@entry=0 '\000') at libbtf.c:750
 #2  0x00007f2f2c1e9af0 in btf_encoder__encode () at btf_encoder.c:164
 #3  0x00005654e2407599 in main (argc=3, argv=0x7ffcd8783f18) at pahole.c:1344
(gdb) frame 1
 #1  0x00007f2f2c1ec2ee in btf_elf__encode (btfe=0x5654e31e2e30, flags=flags@entry=0 '\000') at libbtf.c:750
750             gobuffer__copy(btfe->strings, btf_elf__nohdr_data(btfe) + hdr->str_off);
(gdb) print btfe->strings
$1 = (struct gobuffer *) 0x5654e31db2c8
(gdb) print *btfe->strings
$2 = {entries = 0x0, nr_entries = 0, index = 1, allocated_size = 0}
(gdb) print btfe->types
$3 = {entries = 0x5654e31e2ef0 "", nr_entries = 1, index = 16, allocated_size = 8192}
(gdb) x /16bx btfe->types.entries
0x5654e31e2ef0: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x01
0x5654e31e2ef8: 0x04    0x00    0x00    0x00    0x20    0x00    0x00    0x00

Signed-off-by: Petr Vandrovec <petr@vmware.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-17 13:54:15 -03:00
Domenico Andreoli cb17f94f46 Add changes-v1.16 to the MANIFEST file
Signed-off-by: Domenico Andreoli <domenico.andreoli@linux.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-17 13:34:37 -03:00
Julia Kartseva 32a19e044c pahole: Fix changelog date in dwarves.spec
Signed-off-by: Julia Kartseva <hex@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-17 13:34:33 -03:00
Arnaldo Carvalho de Melo 9b09f578b7 pahole: Initialize var to silence -Werror=maybe-uninitialized on gcc version 4.8.5 20150623
That str variable _will_ be initialized at that point, but lets set it
to NULL to silence gcc version 4.8.5 20150623.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-17 12:40:37 -03:00
Arnaldo Carvalho de Melo 277c2b3d1b man-pages: Add section about --hex + -E to locate offsets deep into sub structs
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-16 12:10:54 -03:00
Arnaldo Carvalho de Melo 812c980b3f man-pages: Update some info, expand BTF info, add some EXAMPLES
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-16 11:36:20 -03:00
Arnaldo Carvalho de Melo e0942c7b03 pahole: Add support for finding pointers to void
$ pahole --find_pointers_to void --prefix tcp
  tcp_md5sig_pool: scratch
  $ pahole tcp_md5sig_pool
  struct tcp_md5sig_pool {
  	struct ahash_request *     md5_req;              /*     0     8 */
  	void *                     scratch;              /*     8     8 */

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

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-01-15 16:33:41 -03:00