Merge tag 'printk-for-5.10-rc6-fixup' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / tools / lib / traceevent / kbuffer-parse.c
1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3  * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4  *
5  */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "kbuffer.h"
11
12 #define MISSING_EVENTS (1UL << 31)
13 #define MISSING_STORED (1UL << 30)
14
15 #define COMMIT_MASK ((1 << 27) - 1)
16
17 enum {
18         KBUFFER_FL_HOST_BIG_ENDIAN      = (1<<0),
19         KBUFFER_FL_BIG_ENDIAN           = (1<<1),
20         KBUFFER_FL_LONG_8               = (1<<2),
21         KBUFFER_FL_OLD_FORMAT           = (1<<3),
22 };
23
24 #define ENDIAN_MASK (KBUFFER_FL_HOST_BIG_ENDIAN | KBUFFER_FL_BIG_ENDIAN)
25
26 /** kbuffer
27  * @timestamp           - timestamp of current event
28  * @lost_events         - # of lost events between this subbuffer and previous
29  * @flags               - special flags of the kbuffer
30  * @subbuffer           - pointer to the sub-buffer page
31  * @data                - pointer to the start of data on the sub-buffer page
32  * @index               - index from @data to the @curr event data
33  * @curr                - offset from @data to the start of current event
34  *                         (includes metadata)
35  * @next                - offset from @data to the start of next event
36  * @size                - The size of data on @data
37  * @start               - The offset from @subbuffer where @data lives
38  *
39  * @read_4              - Function to read 4 raw bytes (may swap)
40  * @read_8              - Function to read 8 raw bytes (may swap)
41  * @read_long           - Function to read a long word (4 or 8 bytes with needed swap)
42  */
43 struct kbuffer {
44         unsigned long long      timestamp;
45         long long               lost_events;
46         unsigned long           flags;
47         void                    *subbuffer;
48         void                    *data;
49         unsigned int            index;
50         unsigned int            curr;
51         unsigned int            next;
52         unsigned int            size;
53         unsigned int            start;
54
55         unsigned int (*read_4)(void *ptr);
56         unsigned long long (*read_8)(void *ptr);
57         unsigned long long (*read_long)(struct kbuffer *kbuf, void *ptr);
58         int (*next_event)(struct kbuffer *kbuf);
59 };
60
61 static void *zmalloc(size_t size)
62 {
63         return calloc(1, size);
64 }
65
66 static int host_is_bigendian(void)
67 {
68         unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };
69         unsigned int *ptr;
70
71         ptr = (unsigned int *)str;
72         return *ptr == 0x01020304;
73 }
74
75 static int do_swap(struct kbuffer *kbuf)
76 {
77         return ((kbuf->flags & KBUFFER_FL_HOST_BIG_ENDIAN) + kbuf->flags) &
78                 ENDIAN_MASK;
79 }
80
81 static unsigned long long __read_8(void *ptr)
82 {
83         unsigned long long data = *(unsigned long long *)ptr;
84
85         return data;
86 }
87
88 static unsigned long long __read_8_sw(void *ptr)
89 {
90         unsigned long long data = *(unsigned long long *)ptr;
91         unsigned long long swap;
92
93         swap = ((data & 0xffULL) << 56) |
94                 ((data & (0xffULL << 8)) << 40) |
95                 ((data & (0xffULL << 16)) << 24) |
96                 ((data & (0xffULL << 24)) << 8) |
97                 ((data & (0xffULL << 32)) >> 8) |
98                 ((data & (0xffULL << 40)) >> 24) |
99                 ((data & (0xffULL << 48)) >> 40) |
100                 ((data & (0xffULL << 56)) >> 56);
101
102         return swap;
103 }
104
105 static unsigned int __read_4(void *ptr)
106 {
107         unsigned int data = *(unsigned int *)ptr;
108
109         return data;
110 }
111
112 static unsigned int __read_4_sw(void *ptr)
113 {
114         unsigned int data = *(unsigned int *)ptr;
115         unsigned int swap;
116
117         swap = ((data & 0xffULL) << 24) |
118                 ((data & (0xffULL << 8)) << 8) |
119                 ((data & (0xffULL << 16)) >> 8) |
120                 ((data & (0xffULL << 24)) >> 24);
121
122         return swap;
123 }
124
125 static unsigned long long read_8(struct kbuffer *kbuf, void *ptr)
126 {
127         return kbuf->read_8(ptr);
128 }
129
130 static unsigned int read_4(struct kbuffer *kbuf, void *ptr)
131 {
132         return kbuf->read_4(ptr);
133 }
134
135 static unsigned long long __read_long_8(struct kbuffer *kbuf, void *ptr)
136 {
137         return kbuf->read_8(ptr);
138 }
139
140 static unsigned long long __read_long_4(struct kbuffer *kbuf, void *ptr)
141 {
142         return kbuf->read_4(ptr);
143 }
144
145 static unsigned long long read_long(struct kbuffer *kbuf, void *ptr)
146 {
147         return kbuf->read_long(kbuf, ptr);
148 }
149
150 static int calc_index(struct kbuffer *kbuf, void *ptr)
151 {
152         return (unsigned long)ptr - (unsigned long)kbuf->data;
153 }
154
155 static int __next_event(struct kbuffer *kbuf);
156
157 /**
158  * kbuffer_alloc - allocat a new kbuffer
159  * @size;       enum to denote size of word
160  * @endian:     enum to denote endianness
161  *
162  * Allocates and returns a new kbuffer.
163  */
164 struct kbuffer *
165 kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian)
166 {
167         struct kbuffer *kbuf;
168         int flags = 0;
169
170         switch (size) {
171         case KBUFFER_LSIZE_4:
172                 break;
173         case KBUFFER_LSIZE_8:
174                 flags |= KBUFFER_FL_LONG_8;
175                 break;
176         default:
177                 return NULL;
178         }
179
180         switch (endian) {
181         case KBUFFER_ENDIAN_LITTLE:
182                 break;
183         case KBUFFER_ENDIAN_BIG:
184                 flags |= KBUFFER_FL_BIG_ENDIAN;
185                 break;
186         default:
187                 return NULL;
188         }
189
190         kbuf = zmalloc(sizeof(*kbuf));
191         if (!kbuf)
192                 return NULL;
193
194         kbuf->flags = flags;
195
196         if (host_is_bigendian())
197                 kbuf->flags |= KBUFFER_FL_HOST_BIG_ENDIAN;
198
199         if (do_swap(kbuf)) {
200                 kbuf->read_8 = __read_8_sw;
201                 kbuf->read_4 = __read_4_sw;
202         } else {
203                 kbuf->read_8 = __read_8;
204                 kbuf->read_4 = __read_4;
205         }
206
207         if (kbuf->flags & KBUFFER_FL_LONG_8)
208                 kbuf->read_long = __read_long_8;
209         else
210                 kbuf->read_long = __read_long_4;
211
212         /* May be changed by kbuffer_set_old_format() */
213         kbuf->next_event = __next_event;
214
215         return kbuf;
216 }
217
218 /** kbuffer_free - free an allocated kbuffer
219  * @kbuf:       The kbuffer to free
220  *
221  * Can take NULL as a parameter.
222  */
223 void kbuffer_free(struct kbuffer *kbuf)
224 {
225         free(kbuf);
226 }
227
228 static unsigned int type4host(struct kbuffer *kbuf,
229                               unsigned int type_len_ts)
230 {
231         if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
232                 return (type_len_ts >> 29) & 3;
233         else
234                 return type_len_ts & 3;
235 }
236
237 static unsigned int len4host(struct kbuffer *kbuf,
238                              unsigned int type_len_ts)
239 {
240         if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
241                 return (type_len_ts >> 27) & 7;
242         else
243                 return (type_len_ts >> 2) & 7;
244 }
245
246 static unsigned int type_len4host(struct kbuffer *kbuf,
247                                   unsigned int type_len_ts)
248 {
249         if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
250                 return (type_len_ts >> 27) & ((1 << 5) - 1);
251         else
252                 return type_len_ts & ((1 << 5) - 1);
253 }
254
255 static unsigned int ts4host(struct kbuffer *kbuf,
256                             unsigned int type_len_ts)
257 {
258         if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
259                 return type_len_ts & ((1 << 27) - 1);
260         else
261                 return type_len_ts >> 5;
262 }
263
264 /*
265  * Linux 2.6.30 and earlier (not much ealier) had a different
266  * ring buffer format. It should be obsolete, but we handle it anyway.
267  */
268 enum old_ring_buffer_type {
269         OLD_RINGBUF_TYPE_PADDING,
270         OLD_RINGBUF_TYPE_TIME_EXTEND,
271         OLD_RINGBUF_TYPE_TIME_STAMP,
272         OLD_RINGBUF_TYPE_DATA,
273 };
274
275 static unsigned int old_update_pointers(struct kbuffer *kbuf)
276 {
277         unsigned long long extend;
278         unsigned int type_len_ts;
279         unsigned int type;
280         unsigned int len;
281         unsigned int delta;
282         unsigned int length;
283         void *ptr = kbuf->data + kbuf->curr;
284
285         type_len_ts = read_4(kbuf, ptr);
286         ptr += 4;
287
288         type = type4host(kbuf, type_len_ts);
289         len = len4host(kbuf, type_len_ts);
290         delta = ts4host(kbuf, type_len_ts);
291
292         switch (type) {
293         case OLD_RINGBUF_TYPE_PADDING:
294                 kbuf->next = kbuf->size;
295                 return 0;
296
297         case OLD_RINGBUF_TYPE_TIME_EXTEND:
298                 extend = read_4(kbuf, ptr);
299                 extend <<= TS_SHIFT;
300                 extend += delta;
301                 delta = extend;
302                 ptr += 4;
303                 length = 0;
304                 break;
305
306         case OLD_RINGBUF_TYPE_TIME_STAMP:
307                 /* should never happen! */
308                 kbuf->curr = kbuf->size;
309                 kbuf->next = kbuf->size;
310                 kbuf->index = kbuf->size;
311                 return -1;
312         default:
313                 if (len)
314                         length = len * 4;
315                 else {
316                         length = read_4(kbuf, ptr);
317                         length -= 4;
318                         ptr += 4;
319                 }
320                 break;
321         }
322
323         kbuf->timestamp += delta;
324         kbuf->index = calc_index(kbuf, ptr);
325         kbuf->next = kbuf->index + length;
326
327         return type;
328 }
329
330 static int __old_next_event(struct kbuffer *kbuf)
331 {
332         int type;
333
334         do {
335                 kbuf->curr = kbuf->next;
336                 if (kbuf->next >= kbuf->size)
337                         return -1;
338                 type = old_update_pointers(kbuf);
339         } while (type == OLD_RINGBUF_TYPE_TIME_EXTEND || type == OLD_RINGBUF_TYPE_PADDING);
340
341         return 0;
342 }
343
344 static unsigned int
345 translate_data(struct kbuffer *kbuf, void *data, void **rptr,
346                unsigned long long *delta, int *length)
347 {
348         unsigned long long extend;
349         unsigned int type_len_ts;
350         unsigned int type_len;
351
352         type_len_ts = read_4(kbuf, data);
353         data += 4;
354
355         type_len = type_len4host(kbuf, type_len_ts);
356         *delta = ts4host(kbuf, type_len_ts);
357
358         switch (type_len) {
359         case KBUFFER_TYPE_PADDING:
360                 *length = read_4(kbuf, data);
361                 break;
362
363         case KBUFFER_TYPE_TIME_EXTEND:
364         case KBUFFER_TYPE_TIME_STAMP:
365                 extend = read_4(kbuf, data);
366                 data += 4;
367                 extend <<= TS_SHIFT;
368                 extend += *delta;
369                 *delta = extend;
370                 *length = 0;
371                 break;
372
373         case 0:
374                 *length = read_4(kbuf, data) - 4;
375                 *length = (*length + 3) & ~3;
376                 data += 4;
377                 break;
378         default:
379                 *length = type_len * 4;
380                 break;
381         }
382
383         *rptr = data;
384
385         return type_len;
386 }
387
388 static unsigned int update_pointers(struct kbuffer *kbuf)
389 {
390         unsigned long long delta;
391         unsigned int type_len;
392         int length;
393         void *ptr = kbuf->data + kbuf->curr;
394
395         type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
396
397         if (type_len == KBUFFER_TYPE_TIME_STAMP)
398                 kbuf->timestamp = delta;
399         else
400                 kbuf->timestamp += delta;
401
402         kbuf->index = calc_index(kbuf, ptr);
403         kbuf->next = kbuf->index + length;
404
405         return type_len;
406 }
407
408 /**
409  * kbuffer_translate_data - read raw data to get a record
410  * @swap:       Set to 1 if bytes in words need to be swapped when read
411  * @data:       The raw data to read
412  * @size:       Address to store the size of the event data.
413  *
414  * Returns a pointer to the event data. To determine the entire
415  * record size (record metadata + data) just add the difference between
416  * @data and the returned value to @size.
417  */
418 void *kbuffer_translate_data(int swap, void *data, unsigned int *size)
419 {
420         unsigned long long delta;
421         struct kbuffer kbuf;
422         int type_len;
423         int length;
424         void *ptr;
425
426         if (swap) {
427                 kbuf.read_8 = __read_8_sw;
428                 kbuf.read_4 = __read_4_sw;
429                 kbuf.flags = host_is_bigendian() ? 0 : KBUFFER_FL_BIG_ENDIAN;
430         } else {
431                 kbuf.read_8 = __read_8;
432                 kbuf.read_4 = __read_4;
433                 kbuf.flags = host_is_bigendian() ? KBUFFER_FL_BIG_ENDIAN: 0;
434         }
435
436         type_len = translate_data(&kbuf, data, &ptr, &delta, &length);
437         switch (type_len) {
438         case KBUFFER_TYPE_PADDING:
439         case KBUFFER_TYPE_TIME_EXTEND:
440         case KBUFFER_TYPE_TIME_STAMP:
441                 return NULL;
442         }
443
444         *size = length;
445
446         return ptr;
447 }
448
449 static int __next_event(struct kbuffer *kbuf)
450 {
451         int type;
452
453         do {
454                 kbuf->curr = kbuf->next;
455                 if (kbuf->next >= kbuf->size)
456                         return -1;
457                 type = update_pointers(kbuf);
458         } while (type == KBUFFER_TYPE_TIME_EXTEND ||
459                  type == KBUFFER_TYPE_TIME_STAMP ||
460                  type == KBUFFER_TYPE_PADDING);
461
462         return 0;
463 }
464
465 static int next_event(struct kbuffer *kbuf)
466 {
467         return kbuf->next_event(kbuf);
468 }
469
470 /**
471  * kbuffer_next_event - increment the current pointer
472  * @kbuf:       The kbuffer to read
473  * @ts:         Address to store the next record's timestamp (may be NULL to ignore)
474  *
475  * Increments the pointers into the subbuffer of the kbuffer to point to the
476  * next event so that the next kbuffer_read_event() will return a
477  * new event.
478  *
479  * Returns the data of the next event if a new event exists on the subbuffer,
480  * NULL otherwise.
481  */
482 void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts)
483 {
484         int ret;
485
486         if (!kbuf || !kbuf->subbuffer)
487                 return NULL;
488
489         ret = next_event(kbuf);
490         if (ret < 0)
491                 return NULL;
492
493         if (ts)
494                 *ts = kbuf->timestamp;
495
496         return kbuf->data + kbuf->index;
497 }
498
499 /**
500  * kbuffer_load_subbuffer - load a new subbuffer into the kbuffer
501  * @kbuf:       The kbuffer to load
502  * @subbuffer:  The subbuffer to load into @kbuf.
503  *
504  * Load a new subbuffer (page) into @kbuf. This will reset all
505  * the pointers and update the @kbuf timestamp. The next read will
506  * return the first event on @subbuffer.
507  *
508  * Returns 0 on succes, -1 otherwise.
509  */
510 int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer)
511 {
512         unsigned long long flags;
513         void *ptr = subbuffer;
514
515         if (!kbuf || !subbuffer)
516                 return -1;
517
518         kbuf->subbuffer = subbuffer;
519
520         kbuf->timestamp = read_8(kbuf, ptr);
521         ptr += 8;
522
523         kbuf->curr = 0;
524
525         if (kbuf->flags & KBUFFER_FL_LONG_8)
526                 kbuf->start = 16;
527         else
528                 kbuf->start = 12;
529
530         kbuf->data = subbuffer + kbuf->start;
531
532         flags = read_long(kbuf, ptr);
533         kbuf->size = (unsigned int)flags & COMMIT_MASK;
534
535         if (flags & MISSING_EVENTS) {
536                 if (flags & MISSING_STORED) {
537                         ptr = kbuf->data + kbuf->size;
538                         kbuf->lost_events = read_long(kbuf, ptr);
539                 } else
540                         kbuf->lost_events = -1;
541         } else
542                 kbuf->lost_events = 0;
543
544         kbuf->index = 0;
545         kbuf->next = 0;
546
547         next_event(kbuf);
548
549         return 0;
550 }
551
552 /**
553  * kbuffer_subbuf_timestamp - read the timestamp from a sub buffer
554  * @kbuf:      The kbuffer to load
555  * @subbuf:    The subbuffer to read from.
556  *
557  * Return the timestamp from a subbuffer.
558  */
559 unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf)
560 {
561         return kbuf->read_8(subbuf);
562 }
563
564 /**
565  * kbuffer_ptr_delta - read the delta field from a record
566  * @kbuf:      The kbuffer to load
567  * @ptr:       The record in the buffe.
568  *
569  * Return the timestamp delta from a record
570  */
571 unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr)
572 {
573         unsigned int type_len_ts;
574
575         type_len_ts = read_4(kbuf, ptr);
576         return ts4host(kbuf, type_len_ts);
577 }
578
579
580 /**
581  * kbuffer_read_event - read the next event in the kbuffer subbuffer
582  * @kbuf:       The kbuffer to read from
583  * @ts:         The address to store the timestamp of the event (may be NULL to ignore)
584  *
585  * Returns a pointer to the data part of the current event.
586  * NULL if no event is left on the subbuffer.
587  */
588 void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts)
589 {
590         if (!kbuf || !kbuf->subbuffer)
591                 return NULL;
592
593         if (kbuf->curr >= kbuf->size)
594                 return NULL;
595
596         if (ts)
597                 *ts = kbuf->timestamp;
598         return kbuf->data + kbuf->index;
599 }
600
601 /**
602  * kbuffer_timestamp - Return the timestamp of the current event
603  * @kbuf:       The kbuffer to read from
604  *
605  * Returns the timestamp of the current (next) event.
606  */
607 unsigned long long kbuffer_timestamp(struct kbuffer *kbuf)
608 {
609         return kbuf->timestamp;
610 }
611
612 /**
613  * kbuffer_read_at_offset - read the event that is at offset
614  * @kbuf:       The kbuffer to read from
615  * @offset:     The offset into the subbuffer
616  * @ts:         The address to store the timestamp of the event (may be NULL to ignore)
617  *
618  * The @offset must be an index from the @kbuf subbuffer beginning.
619  * If @offset is bigger than the stored subbuffer, NULL will be returned.
620  *
621  * Returns the data of the record that is at @offset. Note, @offset does
622  * not need to be the start of the record, the offset just needs to be
623  * in the record (or beginning of it).
624  *
625  * Note, the kbuf timestamp and pointers are updated to the
626  * returned record. That is, kbuffer_read_event() will return the same
627  * data and timestamp, and kbuffer_next_event() will increment from
628  * this record.
629  */
630 void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset,
631                              unsigned long long *ts)
632 {
633         void *data;
634
635         if (offset < kbuf->start)
636                 offset = 0;
637         else
638                 offset -= kbuf->start;
639
640         /* Reset the buffer */
641         kbuffer_load_subbuffer(kbuf, kbuf->subbuffer);
642         data = kbuffer_read_event(kbuf, ts);
643
644         while (kbuf->curr < offset) {
645                 data = kbuffer_next_event(kbuf, ts);
646                 if (!data)
647                         break;
648         }
649
650         return data;
651 }
652
653 /**
654  * kbuffer_subbuffer_size - the size of the loaded subbuffer
655  * @kbuf:       The kbuffer to read from
656  *
657  * Returns the size of the subbuffer. Note, this size is
658  * where the last event resides. The stored subbuffer may actually be
659  * bigger due to padding and such.
660  */
661 int kbuffer_subbuffer_size(struct kbuffer *kbuf)
662 {
663         return kbuf->size;
664 }
665
666 /**
667  * kbuffer_curr_index - Return the index of the record
668  * @kbuf:       The kbuffer to read from
669  *
670  * Returns the index from the start of the data part of
671  * the subbuffer to the current location. Note this is not
672  * from the start of the subbuffer. An index of zero will
673  * point to the first record. Use kbuffer_curr_offset() for
674  * the actually offset (that can be used by kbuffer_read_at_offset())
675  */
676 int kbuffer_curr_index(struct kbuffer *kbuf)
677 {
678         return kbuf->curr;
679 }
680
681 /**
682  * kbuffer_curr_offset - Return the offset of the record
683  * @kbuf:       The kbuffer to read from
684  *
685  * Returns the offset from the start of the subbuffer to the
686  * current location.
687  */
688 int kbuffer_curr_offset(struct kbuffer *kbuf)
689 {
690         return kbuf->curr + kbuf->start;
691 }
692
693 /**
694  * kbuffer_event_size - return the size of the event data
695  * @kbuf:       The kbuffer to read
696  *
697  * Returns the size of the event data (the payload not counting
698  * the meta data of the record) of the current event.
699  */
700 int kbuffer_event_size(struct kbuffer *kbuf)
701 {
702         return kbuf->next - kbuf->index;
703 }
704
705 /**
706  * kbuffer_curr_size - return the size of the entire record
707  * @kbuf:       The kbuffer to read
708  *
709  * Returns the size of the entire record (meta data and payload)
710  * of the current event.
711  */
712 int kbuffer_curr_size(struct kbuffer *kbuf)
713 {
714         return kbuf->next - kbuf->curr;
715 }
716
717 /**
718  * kbuffer_missed_events - return the # of missed events from last event.
719  * @kbuf:       The kbuffer to read from
720  *
721  * Returns the # of missed events (if recorded) before the current
722  * event. Note, only events on the beginning of a subbuffer can
723  * have missed events, all other events within the buffer will be
724  * zero.
725  */
726 int kbuffer_missed_events(struct kbuffer *kbuf)
727 {
728         /* Only the first event can have missed events */
729         if (kbuf->curr)
730                 return 0;
731
732         return kbuf->lost_events;
733 }
734
735 /**
736  * kbuffer_set_old_forma - set the kbuffer to use the old format parsing
737  * @kbuf:       The kbuffer to set
738  *
739  * This is obsolete (or should be). The first kernels to use the
740  * new ring buffer had a slightly different ring buffer format
741  * (2.6.30 and earlier). It is still somewhat supported by kbuffer,
742  * but should not be counted on in the future.
743  */
744 void kbuffer_set_old_format(struct kbuffer *kbuf)
745 {
746         kbuf->flags |= KBUFFER_FL_OLD_FORMAT;
747
748         kbuf->next_event = __old_next_event;
749 }
750
751 /**
752  * kbuffer_start_of_data - return offset of where data starts on subbuffer
753  * @kbuf:       The kbuffer
754  *
755  * Returns the location on the subbuffer where the data starts.
756  */
757 int kbuffer_start_of_data(struct kbuffer *kbuf)
758 {
759         return kbuf->start;
760 }
761
762 /**
763  * kbuffer_raw_get - get raw buffer info
764  * @kbuf:       The kbuffer
765  * @subbuf:     Start of mapped subbuffer
766  * @info:       Info descriptor to fill in
767  *
768  * For debugging. This can return internals of the ring buffer.
769  * Expects to have info->next set to what it will read.
770  * The type, length and timestamp delta will be filled in, and
771  * @info->next will be updated to the next element.
772  * The @subbuf is used to know if the info is passed the end of
773  * data and NULL will be returned if it is.
774  */
775 struct kbuffer_raw_info *
776 kbuffer_raw_get(struct kbuffer *kbuf, void *subbuf, struct kbuffer_raw_info *info)
777 {
778         unsigned long long flags;
779         unsigned long long delta;
780         unsigned int type_len;
781         unsigned int size;
782         int start;
783         int length;
784         void *ptr = info->next;
785
786         if (!kbuf || !subbuf)
787                 return NULL;
788
789         if (kbuf->flags & KBUFFER_FL_LONG_8)
790                 start = 16;
791         else
792                 start = 12;
793
794         flags = read_long(kbuf, subbuf + 8);
795         size = (unsigned int)flags & COMMIT_MASK;
796
797         if (ptr < subbuf || ptr >= subbuf + start + size)
798                 return NULL;
799
800         type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
801
802         info->next = ptr + length;
803
804         info->type = type_len;
805         info->delta = delta;
806         info->length = length;
807
808         return info;
809 }