From: Arnaldo Carvalho de Melo <acme-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
To: dwarves-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: Joe Lawrence
<joe.lawrence-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>,
Jiri Olsa <jolsa-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
Namhyung Kim <namhyung-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
Andrii Nakryiko
<andrii.nakryiko-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
Song Liu <songliubraving-b10kYP2dOMg@public.gmane.org>
Subject: pahole and parsing data: --seek_bytes, dissecting perf.data files
Date: Wed, 1 Jul 2020 09:46:16 -0300 [thread overview]
Message-ID: <20200701124616.GS29008@kernel.org> (raw)
In-Reply-To: <20200701114421.GR29008-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Em Wed, Jul 01, 2020 at 08:44:21AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Wed, Jul 01, 2020 at 08:25:34AM -0300, Arnaldo Carvalho de Melo escreveu:
> > The latest changeset shows what this is about, see its example
> > below, please help testing and suggesting whatever needs you have
> > regarding pretty printing.
> >
> > Now to implement --skip.
> Now to implement --seek, this time in bytes, so that we can, for
> instance, pretty print perf.data records, looking at 'perf report -D'
> and getting the offset of the start of a series of 'struct
> perf_event_attr' or 'struct perf_event_header'.
Here it is with more complex examples dissecting perf.data file data
structures, including BPF related structs:
commit fe284221448c950d2ba17bce91d19c484d6580a0
Author: Arnaldo Carvalho de Melo <acme-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Date: Wed Jul 1 09:17:38 2020 -0300
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-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
diff --git a/dwarves.h b/dwarves.h
index 24f9c7c37843..1b118d03ec15 100644
--- a/dwarves.h
+++ b/dwarves.h
@@ -13,6 +13,7 @@
#include <obstack.h>
#include <dwarf.h>
#include <elfutils/libdwfl.h>
+#include <sys/types.h>
#include "dutil.h"
#include "list.h"
@@ -56,6 +57,7 @@ struct conf_load {
*
* @count - Just like 'dd', stop pretty printing input after 'count' records
* @skip - Just like 'dd', skip 'count' records when pretty printing input
+ * @seek_bytes - Number of bytes to seek, if stdin only from start, when we have --pretty FILE, then from the end as well with negative numbers
* @flat_arrays - a->foo[10][2] becomes a->foo[20]
* @classes_as_structs - class f becomes struct f, CTF doesn't have a "class"
* @cachelinep - pointer to current cacheline, so that when expanding types we keep track of it,
@@ -72,6 +74,7 @@ struct conf_fprintf {
uint32_t base_offset;
uint32_t count;
uint32_t *cachelinep;
+ off_t seek_bytes;
uint32_t skip;
uint8_t indent;
uint8_t expand_types:1;
diff --git a/man-pages/pahole.1 b/man-pages/pahole.1
index db820cca323f..ad4e92d716cf 100644
--- a/man-pages/pahole.1
+++ b/man-pages/pahole.1
@@ -516,6 +516,14 @@ $ pahole --skip 1 --count 2 -C modversion_info drivers/scsi/sg.ko < versions
.name = "param_ops_int",
},
$
+This is equivalent to:
+
+$ pahole --seek_bytes 64 --count 1 -C modversion_info drivers/scsi/sg.ko < versions
+{
+ .crc = 0x45e4617b,
+ .name = "no_llseek",
+},
+$
.fi
.P
diff --git a/pahole.c b/pahole.c
index 7d8431c64423..245a3f2f14f7 100644
--- a/pahole.c
+++ b/pahole.c
@@ -3,7 +3,7 @@
Copyright (C) 2006 Mandriva Conectiva S.A.
Copyright (C) 2006 Arnaldo Carvalho de Melo <acme-4qZELD6FgxhWk0Htik3J/w@public.gmane.org>
- Copyright (C) 2007-2008 Arnaldo Carvalho de Melo <acme-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+ Copyright (C) 2007- Arnaldo Carvalho de Melo <acme-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
*/
#include <argp.h>
@@ -804,6 +804,7 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = dwarves_print_version;
#define ARGP_just_structs 310
#define ARGP_count 311
#define ARGP_skip 312
+#define ARGP_seek_bytes 313
static const struct argp_option pahole__options[] = {
{
@@ -836,6 +837,12 @@ static const struct argp_option pahole__options[] = {
.arg = "COUNT",
.doc = "Skip COUNT input records"
},
+ {
+ .name = "seek_bytes",
+ .key = ARGP_seek_bytes,
+ .arg = "BYTES",
+ .doc = "Seek COUNT input records"
+ },
{
.name = "find_pointers_to",
.key = 'f',
@@ -1163,6 +1170,8 @@ static error_t pahole__options_parser(int key, char *arg,
conf.count = atoi(arg); break;
case ARGP_skip:
conf.skip = atoi(arg); break;
+ case ARGP_seek_bytes:
+ conf.seek_bytes = strtol(arg, NULL, 0); break;
default:
return ARGP_ERR_UNKNOWN;
}
@@ -1329,6 +1338,25 @@ static int tag__fprintf_value(struct tag *type, struct cu *cu, void *instance, i
return tag__fprintf_hexdump_value(type, cu, instance, _sizeof, fp);
}
+static int pipe_seek(FILE *fp, off_t offset)
+{
+ char bf[4096];
+ int chunk = sizeof(bf);
+
+ if (chunk > offset)
+ chunk = offset;
+
+ while (fread(bf, chunk, 1, stdin) == 1) {
+ offset -= chunk;
+ if (offset == 0)
+ return 0;
+ if (chunk > offset)
+ chunk = offset;
+ }
+
+ return offset == 0 ? 0 : -1;
+}
+
static int tag__stdio_fprintf_value(struct tag *type, struct cu *cu, FILE *fp)
{
int _sizeof = tag__size(type, cu), printed = 0;
@@ -1339,6 +1367,12 @@ static int tag__stdio_fprintf_value(struct tag *type, struct cu *cu, FILE *fp)
if (instance == NULL)
return -ENOMEM;
+ if (conf.seek_bytes && pipe_seek(stdin, conf.seek_bytes) < 0) {
+ int err = --errno;
+ fprintf(stderr, "Couldn't --seek_bytes %ld\n", conf.seek_bytes);
+ return err;
+ }
+
while (fread(instance, _sizeof, 1, stdin) == 1) {
if (skip) {
--skip;
prev parent reply other threads:[~2020-07-01 12:46 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20200623165646.GA2251@redhat.com>
[not found] ` <e52cf45d-311f-85c7-d358-5592d3666092@redhat.com>
[not found] ` <20200624173038.GC20203@kernel.org>
[not found] ` <20200624185748.GA16165@redhat.com>
[not found] ` <20200624190716.GA4139@redhat.com>
[not found] ` <a5238972-e36e-3abe-aa14-5dcca58c46fb@redhat.com>
[not found] ` <20200625113816.GA29008@kernel.org>
[not found] ` <20200625114129.GB29008@kernel.org>
[not found] ` <20200625160326.GA10325@kernel.org>
[not found] ` <0eae329c-d448-4d04-c240-0850a93278a5@redhat.com>
[not found] ` <0eae329c-d448-4d04-c240-0850a93278a5-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2020-07-01 11:25 ` pahole and parsing data: --count Arnaldo Carvalho de Melo
[not found] ` <20200701112534.GQ29008-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2020-07-01 11:44 ` pahole and parsing data: --skip Arnaldo Carvalho de Melo
[not found] ` <20200701114421.GR29008-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2020-07-01 12:46 ` Arnaldo Carvalho de Melo [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200701124616.GS29008@kernel.org \
--to=acme-dgejt+ai2ygdnm+yrofe0a@public.gmane.org \
--cc=andrii.nakryiko-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=dwarves-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=joe.lawrence-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
--cc=jolsa-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=namhyung-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=songliubraving-b10kYP2dOMg@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.