static int process_sample_event(event_t *event)
 {
-       u64 ip = event->ip.ip;
-       u64 timestamp = -1;
-       u32 cpu = -1;
-       u64 period = 1;
-       void *more_data = event->ip.__more_data;
-       struct thread *thread = threads__findnew(event->ip.pid);
-
-       if (sample_type & PERF_SAMPLE_TIME) {
-               timestamp = *(u64 *)more_data;
-               more_data += sizeof(u64);
-       }
+       struct sample_data data;
+       struct thread *thread;
 
-       if (sample_type & PERF_SAMPLE_CPU) {
-               cpu = *(u32 *)more_data;
-               more_data += sizeof(u32);
-               more_data += sizeof(u32); /* reserved */
-       }
+       memset(&data, 0, sizeof(data));
+       data.time = -1;
+       data.cpu = -1;
+       data.period = 1;
 
-       if (sample_type & PERF_SAMPLE_PERIOD) {
-               period = *(u64 *)more_data;
-               more_data += sizeof(u64);
-       }
+       event__parse_sample(event, sample_type, &data);
 
        dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
                event->header.misc,
-               event->ip.pid, event->ip.tid,
-               (void *)(long)ip,
-               (long long)period);
+               data.pid, data.tid,
+               (void *)(long)data.ip,
+               (long long)data.period);
 
+       thread = threads__findnew(event->ip.pid);
        if (thread == NULL) {
                pr_debug("problem processing %d event, skipping it.\n",
                         event->header.type);
 
        dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
 
-       process_raw_event(event, more_data, cpu, timestamp, thread);
+       process_raw_event(event, data.raw_data, data.cpu, data.time, thread);
 
        return 0;
 }
 
 
 static int process_sample_event(event_t *event)
 {
-       u64 ip = event->ip.ip;
-       u64 period = 1;
-       void *more_data = event->ip.__more_data;
-       struct ip_callchain *chain = NULL;
+       struct sample_data data;
        int cpumode;
        struct addr_location al;
-       struct thread *thread = threads__findnew(event->ip.pid);
+       struct thread *thread;
 
-       if (sample_type & PERF_SAMPLE_PERIOD) {
-               period = *(u64 *)more_data;
-               more_data += sizeof(u64);
-       }
+       memset(&data, 0, sizeof(data));
+       data.period = 1;
+
+       event__parse_sample(event, sample_type, &data);
 
        dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
                event->header.misc,
-               event->ip.pid, event->ip.tid,
-               (void *)(long)ip,
-               (long long)period);
+               data.pid, data.tid,
+               (void *)(long)data.ip,
+               (long long)data.period);
 
        if (sample_type & PERF_SAMPLE_CALLCHAIN) {
                unsigned int i;
 
-               chain = (void *)more_data;
-
-               dump_printf("... chain: nr:%Lu\n", chain->nr);
+               dump_printf("... chain: nr:%Lu\n", data.callchain->nr);
 
-               if (validate_chain(chain, event) < 0) {
+               if (validate_chain(data.callchain, event) < 0) {
                        pr_debug("call-chain problem with event, "
                                 "skipping it.\n");
                        return 0;
                }
 
                if (dump_trace) {
-                       for (i = 0; i < chain->nr; i++)
-                               dump_printf("..... %2d: %016Lx\n", i, chain->ips[i]);
+                       for (i = 0; i < data.callchain->nr; i++)
+                               dump_printf("..... %2d: %016Lx\n",
+                                           i, data.callchain->ips[i]);
                }
        }
 
+       thread = threads__findnew(data.pid);
        if (thread == NULL) {
                pr_debug("problem processing %d event, skipping it.\n",
                        event->header.type);
        cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
        thread__find_addr_location(thread, cpumode,
-                                  MAP__FUNCTION, ip, &al, NULL);
+                                  MAP__FUNCTION, data.ip, &al, NULL);
        /*
         * We have to do this here as we may have a dso with no symbol hit that
         * has a name longer than the ones with symbols sampled.
        if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name))
                return 0;
 
-       if (hist_entry__add(&al, chain, period)) {
+       if (hist_entry__add(&al, data.callchain, data.period)) {
                pr_debug("problem incrementing symbol count, skipping event\n");
                return -1;
        }
 
-       event__stats.total += period;
+       event__stats.total += data.period;
 
        return 0;
 }
 
 
 static int process_sample_event(event_t *event)
 {
+       struct sample_data data;
        struct thread *thread;
-       u64 ip = event->ip.ip;
-       u64 timestamp = -1;
-       u32 cpu = -1;
-       u64 period = 1;
-       void *more_data = event->ip.__more_data;
 
        if (!(sample_type & PERF_SAMPLE_RAW))
                return 0;
 
-       thread = threads__findnew(event->ip.pid);
+       memset(&data, 0, sizeof(data));
+       data.time = -1;
+       data.cpu = -1;
+       data.period = -1;
 
-       if (sample_type & PERF_SAMPLE_TIME) {
-               timestamp = *(u64 *)more_data;
-               more_data += sizeof(u64);
-       }
-
-       if (sample_type & PERF_SAMPLE_CPU) {
-               cpu = *(u32 *)more_data;
-               more_data += sizeof(u32);
-               more_data += sizeof(u32); /* reserved */
-       }
-
-       if (sample_type & PERF_SAMPLE_PERIOD) {
-               period = *(u64 *)more_data;
-               more_data += sizeof(u64);
-       }
+       event__parse_sample(event, sample_type, &data);
 
        dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
                event->header.misc,
-               event->ip.pid, event->ip.tid,
-               (void *)(long)ip,
-               (long long)period);
+               data.pid, data.tid,
+               (void *)(long)data.ip,
+               (long long)data.period);
 
+       thread = threads__findnew(data.pid);
        if (thread == NULL) {
                pr_debug("problem processing %d event, skipping it.\n",
                         event->header.type);
 
        dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
 
-       if (profile_cpu != -1 && profile_cpu != (int) cpu)
+       if (profile_cpu != -1 && profile_cpu != (int)data.cpu)
                return 0;
 
-       process_raw_event(event, more_data, cpu, timestamp, thread);
+       process_raw_event(event, data.raw_data, data.cpu, data.time, thread);
 
        return 0;
 }
 
 static int
 process_sample_event(event_t *event)
 {
-       int cursor = 0;
-       u64 addr = 0;
-       u64 stamp = 0;
-       u32 cpu = 0;
-       u32 pid = 0;
-       u32 size, *size_ptr;
+       struct sample_data data;
        struct trace_entry *te;
 
-       if (sample_type & PERF_SAMPLE_IP)
-               cursor++;
-
-       if (sample_type & PERF_SAMPLE_TID) {
-               pid = event->sample.array[cursor]>>32;
-               cursor++;
-       }
-       if (sample_type & PERF_SAMPLE_TIME) {
-               stamp = event->sample.array[cursor++];
+       memset(&data, 0, sizeof(data));
 
-               if (!first_time || first_time > stamp)
-                       first_time = stamp;
-               if (last_time < stamp)
-                       last_time = stamp;
+       event__parse_sample(event, sample_type, &data);
 
+       if (sample_type & PERF_SAMPLE_TIME) {
+               if (!first_time || first_time > data.time)
+                       first_time = data.time;
+               if (last_time < data.time)
+                       last_time = data.time;
        }
-       if (sample_type & PERF_SAMPLE_ADDR)
-               addr = event->sample.array[cursor++];
-       if (sample_type & PERF_SAMPLE_ID)
-               cursor++;
-       if (sample_type & PERF_SAMPLE_STREAM_ID)
-               cursor++;
-       if (sample_type & PERF_SAMPLE_CPU)
-               cpu = event->sample.array[cursor++] & 0xFFFFFFFF;
-       if (sample_type & PERF_SAMPLE_PERIOD)
-               cursor++;
-
-       size_ptr = (void *)&event->sample.array[cursor];
-
-       size = *size_ptr;
-       size_ptr++;
 
-       te = (void *)size_ptr;
-       if (sample_type & PERF_SAMPLE_RAW && size > 0) {
+       te = (void *)data.raw_data;
+       if (sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) {
                char *event_str;
                struct power_entry *pe;
 
                        return 0;
 
                if (strcmp(event_str, "power:power_start") == 0)
-                       c_state_start(cpu, stamp, pe->value);
+                       c_state_start(data.cpu, data.time, pe->value);
 
                if (strcmp(event_str, "power:power_end") == 0)
-                       c_state_end(cpu, stamp);
+                       c_state_end(data.cpu, data.time);
 
                if (strcmp(event_str, "power:power_frequency") == 0)
-                       p_state_change(cpu, stamp, pe->value);
+                       p_state_change(data.cpu, data.time, pe->value);
 
                if (strcmp(event_str, "sched:sched_wakeup") == 0)
-                       sched_wakeup(cpu, stamp, pid, te);
+                       sched_wakeup(data.cpu, data.time, data.pid, te);
 
                if (strcmp(event_str, "sched:sched_switch") == 0)
-                       sched_switch(cpu, stamp, te);
+                       sched_switch(data.cpu, data.time, te);
        }
        return 0;
 }
 
 
 static int process_sample_event(event_t *event)
 {
-       u64 ip = event->ip.ip;
-       u64 timestamp = -1;
-       u32 cpu = -1;
-       u64 period = 1;
-       void *more_data = event->ip.__more_data;
-       struct thread *thread = threads__findnew(event->ip.pid);
-
-       if (sample_type & PERF_SAMPLE_TIME) {
-               timestamp = *(u64 *)more_data;
-               more_data += sizeof(u64);
-       }
+       struct sample_data data;
+       struct thread *thread;
 
-       if (sample_type & PERF_SAMPLE_CPU) {
-               cpu = *(u32 *)more_data;
-               more_data += sizeof(u32);
-               more_data += sizeof(u32); /* reserved */
-       }
+       memset(&data, 0, sizeof(data));
+       data.time = -1;
+       data.cpu = -1;
+       data.period = 1;
 
-       if (sample_type & PERF_SAMPLE_PERIOD) {
-               period = *(u64 *)more_data;
-               more_data += sizeof(u64);
-       }
+       event__parse_sample(event, sample_type, &data);
 
        dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
                event->header.misc,
-               event->ip.pid, event->ip.tid,
-               (void *)(long)ip,
-               (long long)period);
+               data.pid, data.tid,
+               (void *)(long)data.ip,
+               (long long)data.period);
 
+       thread = threads__findnew(event->ip.pid);
        if (thread == NULL) {
                pr_debug("problem processing %d event, skipping it.\n",
                         event->header.type);
                return -1;
        }
 
-       dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
-
        if (sample_type & PERF_SAMPLE_RAW) {
-               struct {
-                       u32 size;
-                       char data[0];
-               } *raw = more_data;
-
                /*
                 * FIXME: better resolve from pid from the struct trace_entry
                 * field, although it should be the same than this perf
                 * event pid
                 */
-               scripting_ops->process_event(cpu, raw->data, raw->size,
-                                            timestamp, thread->comm);
+               scripting_ops->process_event(data.cpu, data.raw_data,
+                                            data.raw_size,
+                                            data.time, thread->comm);
        }
-       event__stats.total += period;
+       event__stats.total += data.period;
 
        return 0;
 }
 
                        al->level == 'H' ? "[hypervisor]" : "<not found>");
        return 0;
 }
+
+int event__parse_sample(event_t *event, u64 type, struct sample_data *data)
+{
+       u64 *array = event->sample.array;
+
+       if (type & PERF_SAMPLE_IP) {
+               data->ip = event->ip.ip;
+               array++;
+       }
+
+       if (type & PERF_SAMPLE_TID) {
+               u32 *p = (u32 *)array;
+               data->pid = p[0];
+               data->tid = p[1];
+               array++;
+       }
+
+       if (type & PERF_SAMPLE_TIME) {
+               data->time = *array;
+               array++;
+       }
+
+       if (type & PERF_SAMPLE_ADDR) {
+               data->addr = *array;
+               array++;
+       }
+
+       if (type & PERF_SAMPLE_ID) {
+               data->id = *array;
+               array++;
+       }
+
+       if (type & PERF_SAMPLE_STREAM_ID) {
+               data->stream_id = *array;
+               array++;
+       }
+
+       if (type & PERF_SAMPLE_CPU) {
+               u32 *p = (u32 *)array;
+               data->cpu = *p;
+               array++;
+       }
+
+       if (type & PERF_SAMPLE_PERIOD) {
+               data->period = *array;
+               array++;
+       }
+
+       if (type & PERF_SAMPLE_READ) {
+               pr_debug("PERF_SAMPLE_READ is unsuported for now\n");
+               return -1;
+       }
+
+       if (type & PERF_SAMPLE_CALLCHAIN) {
+               data->callchain = (struct ip_callchain *)array;
+               array += 1 + data->callchain->nr;
+       }
+
+       if (type & PERF_SAMPLE_RAW) {
+               u32 *p = (u32 *)array;
+               data->raw_size = *p;
+               p++;
+               data->raw_data = p;
+       }
+
+       return 0;
+}
 
        u64 id;
 };
 
-struct sample_event{
+struct sample_event {
        struct perf_event_header        header;
        u64 array[];
 };
 
+struct sample_data {
+       u64 ip;
+       u32 pid, tid;
+       u64 time;
+       u64 addr;
+       u64 id;
+       u64 stream_id;
+       u32 cpu;
+       u64 period;
+       struct ip_callchain *callchain;
+       u32 raw_size;
+       void *raw_data;
+};
+
 #define BUILD_ID_SIZE 20
 
 struct build_id_event {
 struct addr_location;
 int event__preprocess_sample(const event_t *self, struct addr_location *al,
                             symbol_filter_t filter);
+int event__parse_sample(event_t *event, u64 type, struct sample_data *data);
 
 #endif /* __PERF_RECORD_H */