1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2007 Mathieu Desnoyers
4 * Complete rewrite from the original version made by XangXiu Yang.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License Version 2.1 as published by the Free Software Foundation.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
29 #include <ltt/compiler.h>
30 #include <ltt/marker.h>
31 #include <ltt/ltt-private.h>
33 #define DEFAULT_MARKERS_NUM 100
34 #define DEFAULT_FIELDS_NUM 1
35 #define MAX_NAME_LEN 1024
37 static inline const char *parse_trace_type(struct marker_info
*info
,
39 char *trace_size
, enum ltt_type
*trace_type
,
40 unsigned long *attributes
)
42 int qualifier
; /* 'h', 'l', or 'L' for integer fields */
43 /* 'z' support added 23/7/1999 S.H. */
44 /* 'z' changed to 'Z' --davidm 1/25/99 */
45 /* 't' added for ptrdiff_t */
47 /* parse attributes. */
51 *attributes
|= LTT_ATTRIBUTE_COMPACT
;
55 *attributes
|= LTT_ATTRIBUTE_NETWORK_BYTE_ORDER
;
60 /* get the conversion qualifier */
62 if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L' ||
63 *fmt
=='Z' || *fmt
== 'z' || *fmt
== 't' ||
64 *fmt
== 'S' || *fmt
== '1' || *fmt
== '2' ||
65 *fmt
== '4' || *fmt
== 8) {
68 if (qualifier
== 'l' && *fmt
== 'l') {
76 *trace_type
= LTT_TYPE_UNSIGNED_INT
;
77 *trace_size
= sizeof(char);
80 *trace_type
= LTT_TYPE_STRING
;
83 *trace_type
= LTT_TYPE_UNSIGNED_INT
;
84 *trace_size
= info
->pointer_size
;
88 *trace_type
= LTT_TYPE_SIGNED_INT
;
94 *trace_type
= LTT_TYPE_UNSIGNED_INT
;
103 *trace_size
= sizeof(long long);
106 *trace_size
= info
->long_size
;
110 *trace_size
= info
->size_t_size
;
113 *trace_size
= info
->pointer_size
;
116 *trace_size
= sizeof(short);
119 *trace_size
= sizeof(uint8_t);
122 *trace_size
= sizeof(guint16
);
125 *trace_size
= sizeof(uint32_t);
128 *trace_size
= sizeof(uint64_t);
131 *trace_size
= info
->int_size
;
140 * Field width and precision are *not* supported.
143 __attribute__((no_instrument_function
))
144 static inline const char *parse_c_type(struct marker_info
*info
,
146 char *c_size
, enum ltt_type
*c_type
)
148 int qualifier
; /* 'h', 'l', or 'L' for integer fields */
149 /* 'z' support added 23/7/1999 S.H. */
150 /* 'z' changed to 'Z' --davidm 1/25/99 */
151 /* 't' added for ptrdiff_t */
153 /* process flags : ignore standard print formats for now. */
165 /* get the conversion qualifier */
167 if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L' ||
168 *fmt
=='Z' || *fmt
== 'z' || *fmt
== 't' ||
172 if (qualifier
== 'l' && *fmt
== 'l') {
180 *c_type
= LTT_TYPE_UNSIGNED_INT
;
181 *c_size
= sizeof(unsigned char);
184 *c_type
= LTT_TYPE_STRING
;
187 *c_type
= LTT_TYPE_UNSIGNED_INT
;
188 *c_size
= info
->pointer_size
;
192 *c_type
= LTT_TYPE_SIGNED_INT
;
198 *c_type
= LTT_TYPE_UNSIGNED_INT
;
207 *c_size
= sizeof(long long);
210 *c_size
= info
->long_size
;
214 *c_size
= info
->size_t_size
;
217 *c_size
= info
->pointer_size
;
220 *c_size
= sizeof(short);
223 *c_size
= info
->int_size
;
230 static inline long add_type(struct marker_info
*info
,
231 long offset
, const char *name
,
232 char trace_size
, enum ltt_type trace_type
,
233 char c_size
, enum ltt_type c_type
, unsigned long attributes
,
234 unsigned int field_count
)
236 struct marker_field
*field
;
237 char tmpname
[MAX_NAME_LEN
];
239 info
->fields
= g_array_set_size(info
->fields
, info
->fields
->len
+1);
240 field
= &g_array_index(info
->fields
, struct marker_field
,
241 info
->fields
->len
-1);
243 field
->name
= g_quark_from_string(name
);
245 snprintf(tmpname
, MAX_NAME_LEN
-1, "field %u", field_count
);
246 field
->name
= g_quark_from_string(tmpname
);
248 field
->type
= trace_type
;
250 switch (trace_type
) {
251 case LTT_TYPE_SIGNED_INT
:
252 case LTT_TYPE_UNSIGNED_INT
:
253 field
->size
= trace_size
;
254 field
->alignment
= trace_size
;
255 field
->attributes
= attributes
;
258 field
->static_offset
= 0;
261 field
->offset
= offset
+ ltt_align(offset
, field
->alignment
,
263 field
->static_offset
= 1;
264 return field
->offset
+ trace_size
;
266 case LTT_TYPE_STRING
:
267 field
->offset
= offset
;
268 field
->size
= 0; /* Variable length, size is 0 */
269 field
->alignment
= 1;
271 field
->static_offset
= 0;
273 field
->static_offset
= 1;
276 g_error("Unexpected type"); //FIXME: compact type
281 long marker_update_fields_offsets(struct marker_info
*info
, const char *data
)
283 struct marker_field
*field
;
287 /* Find the last field with a static offset, then update from there. */
288 for (i
= info
->fields
->len
- 1; i
>= 0; i
--) {
289 field
= &g_array_index(info
->fields
, struct marker_field
, i
);
290 if (field
->static_offset
) {
291 offset
= field
->offset
;
296 for (; i
< info
->fields
->len
; i
++) {
297 field
= &g_array_index(info
->fields
, struct marker_field
, i
);
299 switch (field
->type
) {
300 case LTT_TYPE_SIGNED_INT
:
301 case LTT_TYPE_UNSIGNED_INT
:
302 field
->offset
= offset
+ ltt_align(offset
, field
->alignment
,
304 offset
= field
->offset
+ field
->size
;
306 case LTT_TYPE_STRING
:
307 field
->offset
= offset
;
308 offset
= offset
+ strlen(&data
[offset
]) + 1;
309 // not aligning on pointer size, breaking genevent backward compatibility.
312 g_error("Unexpected type"); //FIXME: compact type
319 static void format_parse(const char *fmt
, struct marker_info
*info
)
321 char trace_size
= 0, c_size
= 0; /*
322 * 0 (unset), 1, 2, 4, 8 bytes.
324 enum ltt_type trace_type
= LTT_TYPE_NONE
, c_type
= LTT_TYPE_NONE
;
325 unsigned long attributes
= 0;
327 const char *name_begin
= NULL
, *name_end
= NULL
;
329 unsigned int field_count
= 1;
332 for (; *fmt
; ++fmt
) {
336 ++fmt
; /* skip first '#' */
337 if (*fmt
== '#') /* Escaped ## */
340 fmt
= parse_trace_type(info
, fmt
, &trace_size
, &trace_type
,
345 ++fmt
; /* skip first '%' */
346 if (*fmt
== '%') /* Escaped %% */
348 fmt
= parse_c_type(info
, fmt
, &c_size
, &c_type
);
350 * Output c types if no trace types has been
355 if (trace_type
== LTT_TYPE_NONE
)
357 if (c_type
== LTT_TYPE_STRING
)
358 trace_type
= LTT_TYPE_STRING
;
359 /* perform trace write */
360 offset
= add_type(info
, offset
, name
, trace_size
,
361 trace_type
, c_size
, c_type
, attributes
, field_count
++);
362 trace_size
= c_size
= 0;
363 trace_type
= c_size
= LTT_TYPE_NONE
;
372 if (!name_end
&& name_begin
) {
376 name
= g_new(char, name_end
- name_begin
+ 1);
377 memcpy(name
, name_begin
, name_end
- name_begin
);
378 name
[name_end
- name_begin
] = '\0';
380 break; /* Skip white spaces */
393 int marker_parse_format(const char *format
, struct marker_info
*info
)
396 g_array_free(info
->fields
, TRUE
);
397 info
->fields
= g_array_sized_new(FALSE
, TRUE
,
398 sizeof(struct marker_field
), DEFAULT_FIELDS_NUM
);
399 format_parse(format
, info
);
403 int marker_format_event(LttTrace
*trace
, GQuark name
, const char *format
)
405 struct marker_info
*info
;
407 info
= g_hash_table_lookup(trace
->markers_hash
, (gconstpointer
)name
);
409 g_error("Got marker format \"%s\", but marker name \"%s\" has no ID yet. "
412 for (; info
!= NULL
; info
= info
->next
) {
414 g_free(info
->format
);
415 info
->format
= g_new(char, strlen(format
)+1);
416 strcpy(info
->format
, format
);
417 if (marker_parse_format(format
, info
))
418 g_error("Error parsing marker format \"%s\" for marker \"%s\"", format
,
419 g_quark_to_string(name
));
424 int marker_id_event(LttTrace
*trace
, GQuark name
, guint16 id
,
425 uint8_t int_size
, uint8_t long_size
, uint8_t pointer_size
,
426 uint8_t size_t_size
, uint8_t alignment
)
428 struct marker_info
*info
, *head
;
431 if (trace
->markers
->len
<= id
)
432 trace
->markers
= g_array_set_size(trace
->markers
, id
+1);
433 info
= &g_array_index(trace
->markers
, struct marker_info
, id
);
435 info
->int_size
= int_size
;
436 info
->long_size
= long_size
;
437 info
->pointer_size
= pointer_size
;
438 info
->size_t_size
= size_t_size
;
439 info
->alignment
= alignment
;
441 head
= g_hash_table_lookup(trace
->markers_hash
, (gconstpointer
)name
);
443 g_hash_table_insert(trace
->markers_hash
, (gpointer
)name
, info
);
445 struct marker_info
*iter
;
446 for (iter
= head
; iter
!= NULL
; iter
= iter
->next
)
447 if (iter
->name
== name
)
450 g_hash_table_replace(trace
->markers_hash
, (gpointer
)name
, info
);
457 int allocate_marker_data(LttTrace
*trace
)
459 /* Init array to 0 */
460 trace
->markers
= g_array_sized_new(FALSE
, TRUE
,
461 sizeof(struct marker_info
), DEFAULT_MARKERS_NUM
);
464 trace
->markers_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
465 if (!trace
->markers_hash
)
470 void destroy_marker_data(LttTrace
*trace
)
473 struct marker_info
*info
;
475 for (i
=0; i
<trace
->markers
->len
; i
++) {
476 info
= &g_array_index(trace
->markers
, struct marker_info
, i
);
478 g_free(info
->format
);
480 g_array_free(info
->fields
, TRUE
);
482 g_array_free(trace
->markers
, TRUE
);
483 g_hash_table_destroy(trace
->markers_hash
);