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>
This commit is contained in:
parent
44af7c02b5
commit
fe28422144
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
36
pahole.c
36
pahole.c
|
@ -3,7 +3,7 @@
|
|||
|
||||
Copyright (C) 2006 Mandriva Conectiva S.A.
|
||||
Copyright (C) 2006 Arnaldo Carvalho de Melo <acme@mandriva.com>
|
||||
Copyright (C) 2007-2008 Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||
Copyright (C) 2007- Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||
*/
|
||||
|
||||
#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;
|
||||
|
|
Loading…
Reference in New Issue