|
@@ -36,6 +36,7 @@ static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
|
|
|
|
|
|
static int dump_trace = 0;
|
|
static int dump_trace = 0;
|
|
#define dprintf(x...) do { if (dump_trace) printf(x); } while (0)
|
|
#define dprintf(x...) do { if (dump_trace) printf(x); } while (0)
|
|
|
|
+#define cdprintf(x...) do { if (dump_trace) color_fprintf(stdout, color, x); } while (0)
|
|
|
|
|
|
static int verbose;
|
|
static int verbose;
|
|
static int full_paths;
|
|
static int full_paths;
|
|
@@ -43,11 +44,19 @@ static int full_paths;
|
|
static unsigned long page_size;
|
|
static unsigned long page_size;
|
|
static unsigned long mmap_window = 32;
|
|
static unsigned long mmap_window = 32;
|
|
|
|
|
|
|
|
+struct ip_chain_event {
|
|
|
|
+ __u16 nr;
|
|
|
|
+ __u16 hv;
|
|
|
|
+ __u16 kernel;
|
|
|
|
+ __u16 user;
|
|
|
|
+ __u64 ips[];
|
|
|
|
+};
|
|
|
|
+
|
|
struct ip_event {
|
|
struct ip_event {
|
|
struct perf_event_header header;
|
|
struct perf_event_header header;
|
|
__u64 ip;
|
|
__u64 ip;
|
|
__u32 pid, tid;
|
|
__u32 pid, tid;
|
|
- __u64 period;
|
|
|
|
|
|
+ unsigned char __more_data[];
|
|
};
|
|
};
|
|
|
|
|
|
struct mmap_event {
|
|
struct mmap_event {
|
|
@@ -944,9 +953,13 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
|
|
__u64 ip = event->ip.ip;
|
|
__u64 ip = event->ip.ip;
|
|
__u64 period = 1;
|
|
__u64 period = 1;
|
|
struct map *map = NULL;
|
|
struct map *map = NULL;
|
|
|
|
+ void *more_data = event->ip.__more_data;
|
|
|
|
+ struct ip_chain_event *chain;
|
|
|
|
|
|
- if (event->header.type & PERF_SAMPLE_PERIOD)
|
|
|
|
- period = event->ip.period;
|
|
|
|
|
|
+ if (event->header.type & PERF_SAMPLE_PERIOD) {
|
|
|
|
+ period = *(__u64 *)more_data;
|
|
|
|
+ more_data += sizeof(__u64);
|
|
|
|
+ }
|
|
|
|
|
|
dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p period: %Ld\n",
|
|
dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p period: %Ld\n",
|
|
(void *)(offset + head),
|
|
(void *)(offset + head),
|
|
@@ -956,6 +969,22 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
|
|
(void *)(long)ip,
|
|
(void *)(long)ip,
|
|
(long long)period);
|
|
(long long)period);
|
|
|
|
|
|
|
|
+ if (event->header.type & PERF_SAMPLE_CALLCHAIN) {
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ chain = (void *)more_data;
|
|
|
|
+
|
|
|
|
+ if (dump_trace) {
|
|
|
|
+ dprintf("... chain: u:%d, k:%d, nr:%d\n",
|
|
|
|
+ chain->user,
|
|
|
|
+ chain->kernel,
|
|
|
|
+ chain->nr);
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < chain->nr; i++)
|
|
|
|
+ dprintf("..... %2d: %p\n", i, (void *)chain->ips[i]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid);
|
|
dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid);
|
|
|
|
|
|
if (thread == NULL) {
|
|
if (thread == NULL) {
|
|
@@ -1098,30 +1127,34 @@ process_period_event(event_t *event, unsigned long offset, unsigned long head)
|
|
static void trace_event(event_t *event)
|
|
static void trace_event(event_t *event)
|
|
{
|
|
{
|
|
unsigned char *raw_event = (void *)event;
|
|
unsigned char *raw_event = (void *)event;
|
|
|
|
+ char *color = PERF_COLOR_BLUE;
|
|
int i, j;
|
|
int i, j;
|
|
|
|
|
|
if (!dump_trace)
|
|
if (!dump_trace)
|
|
return;
|
|
return;
|
|
|
|
|
|
- dprintf(".\n. ... raw event: size %d bytes\n", event->header.size);
|
|
|
|
|
|
+ dprintf(".");
|
|
|
|
+ cdprintf("\n. ... raw event: size %d bytes\n", event->header.size);
|
|
|
|
|
|
for (i = 0; i < event->header.size; i++) {
|
|
for (i = 0; i < event->header.size; i++) {
|
|
- if ((i & 15) == 0)
|
|
|
|
- dprintf(". %04x: ", i);
|
|
|
|
|
|
+ if ((i & 15) == 0) {
|
|
|
|
+ dprintf(".");
|
|
|
|
+ cdprintf(" %04x: ", i);
|
|
|
|
+ }
|
|
|
|
|
|
- dprintf(" %02x", raw_event[i]);
|
|
|
|
|
|
+ cdprintf(" %02x", raw_event[i]);
|
|
|
|
|
|
if (((i & 15) == 15) || i == event->header.size-1) {
|
|
if (((i & 15) == 15) || i == event->header.size-1) {
|
|
- dprintf(" ");
|
|
|
|
|
|
+ cdprintf(" ");
|
|
for (j = 0; j < 15-(i & 15); j++)
|
|
for (j = 0; j < 15-(i & 15); j++)
|
|
- dprintf(" ");
|
|
|
|
|
|
+ cdprintf(" ");
|
|
for (j = 0; j < (i & 15); j++) {
|
|
for (j = 0; j < (i & 15); j++) {
|
|
if (isprint(raw_event[i-15+j]))
|
|
if (isprint(raw_event[i-15+j]))
|
|
- dprintf("%c", raw_event[i-15+j]);
|
|
|
|
|
|
+ cdprintf("%c", raw_event[i-15+j]);
|
|
else
|
|
else
|
|
- dprintf(".");
|
|
|
|
|
|
+ cdprintf(".");
|
|
}
|
|
}
|
|
- dprintf("\n");
|
|
|
|
|
|
+ cdprintf("\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
dprintf(".\n");
|
|
dprintf(".\n");
|