|
@@ -41,8 +41,6 @@
|
|
|
|
|
|
static int input_fd;
|
|
|
|
|
|
-static int read_page;
|
|
|
-
|
|
|
int file_bigendian;
|
|
|
int host_bigendian;
|
|
|
static int long_size;
|
|
@@ -287,205 +285,6 @@ static void read_event_files(struct pevent *pevent)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-struct cpu_data {
|
|
|
- unsigned long long offset;
|
|
|
- unsigned long long size;
|
|
|
- unsigned long long timestamp;
|
|
|
- struct pevent_record *next;
|
|
|
- char *page;
|
|
|
- int cpu;
|
|
|
- int index;
|
|
|
- int page_size;
|
|
|
-};
|
|
|
-
|
|
|
-static struct cpu_data *cpu_data;
|
|
|
-
|
|
|
-static void update_cpu_data_index(int cpu)
|
|
|
-{
|
|
|
- cpu_data[cpu].offset += page_size;
|
|
|
- cpu_data[cpu].size -= page_size;
|
|
|
- cpu_data[cpu].index = 0;
|
|
|
-}
|
|
|
-
|
|
|
-static void get_next_page(int cpu)
|
|
|
-{
|
|
|
- off_t save_seek;
|
|
|
- off_t ret;
|
|
|
-
|
|
|
- if (!cpu_data[cpu].page)
|
|
|
- return;
|
|
|
-
|
|
|
- if (read_page) {
|
|
|
- if (cpu_data[cpu].size <= page_size) {
|
|
|
- free(cpu_data[cpu].page);
|
|
|
- cpu_data[cpu].page = NULL;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- update_cpu_data_index(cpu);
|
|
|
-
|
|
|
- /* other parts of the code may expect the pointer to not move */
|
|
|
- save_seek = lseek(input_fd, 0, SEEK_CUR);
|
|
|
-
|
|
|
- ret = lseek(input_fd, cpu_data[cpu].offset, SEEK_SET);
|
|
|
- if (ret == (off_t)-1)
|
|
|
- die("failed to lseek");
|
|
|
- ret = read(input_fd, cpu_data[cpu].page, page_size);
|
|
|
- if (ret < 0)
|
|
|
- die("failed to read page");
|
|
|
-
|
|
|
- /* reset the file pointer back */
|
|
|
- lseek(input_fd, save_seek, SEEK_SET);
|
|
|
-
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- munmap(cpu_data[cpu].page, page_size);
|
|
|
- cpu_data[cpu].page = NULL;
|
|
|
-
|
|
|
- if (cpu_data[cpu].size <= page_size)
|
|
|
- return;
|
|
|
-
|
|
|
- update_cpu_data_index(cpu);
|
|
|
-
|
|
|
- cpu_data[cpu].page = mmap(NULL, page_size, PROT_READ, MAP_PRIVATE,
|
|
|
- input_fd, cpu_data[cpu].offset);
|
|
|
- if (cpu_data[cpu].page == MAP_FAILED)
|
|
|
- die("failed to mmap cpu %d at offset 0x%llx",
|
|
|
- cpu, cpu_data[cpu].offset);
|
|
|
-}
|
|
|
-
|
|
|
-static unsigned int type_len4host(unsigned int type_len_ts)
|
|
|
-{
|
|
|
- if (file_bigendian)
|
|
|
- return (type_len_ts >> 27) & ((1 << 5) - 1);
|
|
|
- else
|
|
|
- return type_len_ts & ((1 << 5) - 1);
|
|
|
-}
|
|
|
-
|
|
|
-static unsigned int ts4host(unsigned int type_len_ts)
|
|
|
-{
|
|
|
- if (file_bigendian)
|
|
|
- return type_len_ts & ((1 << 27) - 1);
|
|
|
- else
|
|
|
- return type_len_ts >> 5;
|
|
|
-}
|
|
|
-
|
|
|
-static int calc_index(void *ptr, int cpu)
|
|
|
-{
|
|
|
- return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page;
|
|
|
-}
|
|
|
-
|
|
|
-struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu)
|
|
|
-{
|
|
|
- struct pevent_record *data;
|
|
|
- void *page = cpu_data[cpu].page;
|
|
|
- int idx = cpu_data[cpu].index;
|
|
|
- void *ptr = page + idx;
|
|
|
- unsigned long long extend;
|
|
|
- unsigned int type_len_ts;
|
|
|
- unsigned int type_len;
|
|
|
- unsigned int delta;
|
|
|
- unsigned int length = 0;
|
|
|
-
|
|
|
- if (cpu_data[cpu].next)
|
|
|
- return cpu_data[cpu].next;
|
|
|
-
|
|
|
- if (!page)
|
|
|
- return NULL;
|
|
|
-
|
|
|
- if (!idx) {
|
|
|
- /* FIXME: handle header page */
|
|
|
- if (header_page_ts_size != 8)
|
|
|
- die("expected a long long type for timestamp");
|
|
|
- cpu_data[cpu].timestamp = data2host8(pevent, ptr);
|
|
|
- ptr += 8;
|
|
|
- switch (header_page_size_size) {
|
|
|
- case 4:
|
|
|
- cpu_data[cpu].page_size = data2host4(pevent, ptr);
|
|
|
- ptr += 4;
|
|
|
- break;
|
|
|
- case 8:
|
|
|
- cpu_data[cpu].page_size = data2host8(pevent, ptr);
|
|
|
- ptr += 8;
|
|
|
- break;
|
|
|
- default:
|
|
|
- die("bad long size");
|
|
|
- }
|
|
|
- ptr = cpu_data[cpu].page + header_page_data_offset;
|
|
|
- }
|
|
|
-
|
|
|
-read_again:
|
|
|
- idx = calc_index(ptr, cpu);
|
|
|
-
|
|
|
- if (idx >= cpu_data[cpu].page_size) {
|
|
|
- get_next_page(cpu);
|
|
|
- return trace_peek_data(pevent, cpu);
|
|
|
- }
|
|
|
-
|
|
|
- type_len_ts = data2host4(pevent, ptr);
|
|
|
- ptr += 4;
|
|
|
-
|
|
|
- type_len = type_len4host(type_len_ts);
|
|
|
- delta = ts4host(type_len_ts);
|
|
|
-
|
|
|
- switch (type_len) {
|
|
|
- case RINGBUF_TYPE_PADDING:
|
|
|
- if (!delta)
|
|
|
- die("error, hit unexpected end of page");
|
|
|
- length = data2host4(pevent, ptr);
|
|
|
- ptr += 4;
|
|
|
- length *= 4;
|
|
|
- ptr += length;
|
|
|
- goto read_again;
|
|
|
-
|
|
|
- case RINGBUF_TYPE_TIME_EXTEND:
|
|
|
- extend = data2host4(pevent, ptr);
|
|
|
- ptr += 4;
|
|
|
- extend <<= TS_SHIFT;
|
|
|
- extend += delta;
|
|
|
- cpu_data[cpu].timestamp += extend;
|
|
|
- goto read_again;
|
|
|
-
|
|
|
- case RINGBUF_TYPE_TIME_STAMP:
|
|
|
- ptr += 12;
|
|
|
- break;
|
|
|
- case 0:
|
|
|
- length = data2host4(pevent, ptr);
|
|
|
- ptr += 4;
|
|
|
- die("here! length=%d", length);
|
|
|
- break;
|
|
|
- default:
|
|
|
- length = type_len * 4;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- cpu_data[cpu].timestamp += delta;
|
|
|
-
|
|
|
- data = malloc_or_die(sizeof(*data));
|
|
|
- memset(data, 0, sizeof(*data));
|
|
|
-
|
|
|
- data->ts = cpu_data[cpu].timestamp;
|
|
|
- data->size = length;
|
|
|
- data->data = ptr;
|
|
|
- ptr += length;
|
|
|
-
|
|
|
- cpu_data[cpu].index = calc_index(ptr, cpu);
|
|
|
- cpu_data[cpu].next = data;
|
|
|
-
|
|
|
- return data;
|
|
|
-}
|
|
|
-
|
|
|
-struct pevent_record *trace_read_data(struct pevent *pevent, int cpu)
|
|
|
-{
|
|
|
- struct pevent_record *data;
|
|
|
-
|
|
|
- data = trace_peek_data(pevent, cpu);
|
|
|
- cpu_data[cpu].next = NULL;
|
|
|
-
|
|
|
- return data;
|
|
|
-}
|
|
|
-
|
|
|
ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
|
|
|
{
|
|
|
char buf[BUFSIZ];
|