4 * Mathieu Desnoyers, August 2007
12 #include <ltt/compiler.h>
13 #include <ltt/markers.h>
14 #include <ltt/ltt-private.h>
16 #define DEFAULT_MARKERS_NUM 100
17 #define DEFAULT_FIELDS_NUM 1
18 #define MAX_NAME_LEN 1024
20 static inline const char *parse_trace_type(struct marker_info
*info
,
22 char *trace_size
, enum ltt_type
*trace_type
,
23 unsigned long *attributes
)
25 int qualifier
; /* 'h', 'l', or 'L' for integer fields */
26 /* 'z' support added 23/7/1999 S.H. */
27 /* 'z' changed to 'Z' --davidm 1/25/99 */
28 /* 't' added for ptrdiff_t */
30 /* parse attributes. */
34 *attributes
|= LTT_ATTRIBUTE_COMPACT
;
38 *attributes
|= LTT_ATTRIBUTE_NETWORK_BYTE_ORDER
;
43 /* get the conversion qualifier */
45 if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L' ||
46 *fmt
=='Z' || *fmt
== 'z' || *fmt
== 't' ||
47 *fmt
== 'S' || *fmt
== '1' || *fmt
== '2' ||
48 *fmt
== '4' || *fmt
== 8) {
51 if (qualifier
== 'l' && *fmt
== 'l') {
59 *trace_type
= LTT_TYPE_UNSIGNED_INT
;
60 *trace_size
= sizeof(char);
63 *trace_type
= LTT_TYPE_STRING
;
66 *trace_type
= LTT_TYPE_UNSIGNED_INT
;
67 *trace_size
= info
->pointer_size
;
71 *trace_type
= LTT_TYPE_SIGNED_INT
;
77 *trace_type
= LTT_TYPE_UNSIGNED_INT
;
86 *trace_size
= sizeof(long long);
89 *trace_size
= info
->long_size
;
93 *trace_size
= info
->size_t_size
;
96 *trace_size
= info
->pointer_size
;
99 *trace_size
= sizeof(short);
102 *trace_size
= sizeof(uint8_t);
105 *trace_size
= sizeof(guint16
);
108 *trace_size
= sizeof(uint32_t);
111 *trace_size
= sizeof(uint64_t);
114 *trace_size
= info
->int_size
;
123 * Field width and precision are *not* supported.
126 __attribute__((no_instrument_function
))
127 static inline const char *parse_c_type(struct marker_info
*info
,
129 char *c_size
, enum ltt_type
*c_type
)
131 int qualifier
; /* 'h', 'l', or 'L' for integer fields */
132 /* 'z' support added 23/7/1999 S.H. */
133 /* 'z' changed to 'Z' --davidm 1/25/99 */
134 /* 't' added for ptrdiff_t */
136 /* process flags : ignore standard print formats for now. */
148 /* get the conversion qualifier */
150 if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L' ||
151 *fmt
=='Z' || *fmt
== 'z' || *fmt
== 't' ||
155 if (qualifier
== 'l' && *fmt
== 'l') {
163 *c_type
= LTT_TYPE_UNSIGNED_INT
;
164 *c_size
= sizeof(unsigned char);
167 *c_type
= LTT_TYPE_STRING
;
170 *c_type
= LTT_TYPE_UNSIGNED_INT
;
171 *c_size
= info
->pointer_size
;
175 *c_type
= LTT_TYPE_SIGNED_INT
;
181 *c_type
= LTT_TYPE_UNSIGNED_INT
;
190 *c_size
= sizeof(long long);
193 *c_size
= info
->long_size
;
197 *c_size
= info
->size_t_size
;
200 *c_size
= info
->pointer_size
;
203 *c_size
= sizeof(short);
206 *c_size
= info
->int_size
;
213 static inline long add_type(struct marker_info
*info
,
214 long offset
, const char *name
,
215 char trace_size
, enum ltt_type trace_type
,
216 char c_size
, enum ltt_type c_type
, unsigned long attributes
,
217 unsigned int field_count
)
219 struct marker_field
*field
;
220 char tmpname
[MAX_NAME_LEN
];
222 info
->fields
= g_array_set_size(info
->fields
, info
->fields
->len
+1);
223 field
= &g_array_index(info
->fields
, struct marker_field
,
224 info
->fields
->len
-1);
226 field
->name
= g_quark_from_string(name
);
228 snprintf(tmpname
, MAX_NAME_LEN
-1, "field %u", field_count
);
229 field
->name
= g_quark_from_string(tmpname
);
231 field
->type
= trace_type
;
233 switch (trace_type
) {
234 case LTT_TYPE_SIGNED_INT
:
235 case LTT_TYPE_UNSIGNED_INT
:
236 field
->size
= trace_size
;
237 field
->alignment
= trace_size
;
238 field
->attributes
= attributes
;
241 field
->static_offset
= 0;
244 field
->offset
= offset
+ ltt_align(offset
, field
->alignment
,
246 field
->static_offset
= 1;
247 return field
->offset
+ trace_size
;
249 case LTT_TYPE_STRING
:
250 field
->offset
= offset
;
251 field
->size
= 0; /* Variable length, size is 0 */
252 field
->alignment
= 1;
254 field
->static_offset
= 0;
256 field
->static_offset
= 1;
259 g_error("Unexpected type"); //FIXME: compact type
264 long marker_update_fields_offsets(struct marker_info
*info
, const char *data
)
266 struct marker_field
*field
;
270 for (i
= 0; i
< info
->fields
->len
; i
++) {
271 field
= &g_array_index(info
->fields
, struct marker_field
, i
);
273 if (field
->static_offset
)
276 switch (field
->type
) {
277 case LTT_TYPE_SIGNED_INT
:
278 case LTT_TYPE_UNSIGNED_INT
:
279 field
->offset
= offset
+ ltt_align(offset
, field
->alignment
,
281 offset
= field
->offset
+ field
->size
;
283 case LTT_TYPE_STRING
:
284 field
->offset
= offset
;
285 offset
= offset
+ strlen(&data
[offset
]) + 1;
286 // not aligning on pointer size, breaking genevent backward compatibility.
289 g_error("Unexpected type"); //FIXME: compact type
296 static void format_parse(const char *fmt
, struct marker_info
*info
)
298 char trace_size
= 0, c_size
= 0; /*
299 * 0 (unset), 1, 2, 4, 8 bytes.
301 enum ltt_type trace_type
= LTT_TYPE_NONE
, c_type
= LTT_TYPE_NONE
;
302 unsigned long attributes
= 0;
304 const char *name_begin
= NULL
, *name_end
= NULL
;
306 unsigned int field_count
= 1;
308 for (; *fmt
; ++fmt
) {
312 ++fmt
; /* skip first '#' */
313 if (*fmt
== '#') /* Escaped ## */
316 fmt
= parse_trace_type(info
, fmt
, &trace_size
, &trace_type
,
321 ++fmt
; /* skip first '%' */
322 if (*fmt
== '%') /* Escaped %% */
324 fmt
= parse_c_type(info
, fmt
, &c_size
, &c_type
);
326 * Output c types if no trace types has been
331 if (trace_type
== LTT_TYPE_NONE
)
333 if (c_type
== LTT_TYPE_STRING
)
334 trace_type
= LTT_TYPE_STRING
;
335 /* perform trace write */
336 offset
= add_type(info
, offset
, name
, trace_size
,
337 trace_type
, c_size
, c_type
, attributes
, field_count
++);
338 trace_size
= c_size
= 0;
339 trace_type
= c_size
= LTT_TYPE_NONE
;
352 name
= g_new(char, name_end
- name_begin
+ 1);
353 memcpy(name
, name_begin
, name_end
- name_begin
);
354 name
[name_end
- name_begin
] = '\0';
356 break; /* Skip white spaces */
369 int marker_parse_format(const char *format
, struct marker_info
*info
)
372 g_array_free(info
->fields
, TRUE
);
373 info
->fields
= g_array_sized_new(FALSE
, TRUE
,
374 sizeof(struct marker_field
), DEFAULT_FIELDS_NUM
);
375 format_parse(format
, info
);
378 int marker_format_event(LttTrace
*trace
, GQuark name
, const char *format
)
380 struct marker_info
*info
;
382 info
= g_hash_table_lookup(trace
->markers_hash
, (gconstpointer
)name
);
384 g_error("Got marker format %s, but marker name %s has no ID yet. "
387 for (; info
!= NULL
; info
= info
->next
) {
389 g_free(info
->format
);
390 info
->format
= g_new(char, strlen(format
)+1);
391 strcpy(info
->format
, format
);
392 if (marker_parse_format(format
, info
))
393 g_error("Error parsing marker format %s for marker %s", format
,
394 g_quark_to_string(name
));
398 int marker_id_event(LttTrace
*trace
, GQuark name
, guint16 id
,
399 uint8_t int_size
, uint8_t long_size
, uint8_t pointer_size
,
400 uint8_t size_t_size
, uint8_t alignment
)
402 struct marker_info
*info
, *head
;
404 if (trace
->markers
->len
< id
)
405 trace
->markers
= g_array_set_size(trace
->markers
, id
+1);
406 info
= &g_array_index(trace
->markers
, struct marker_info
, id
);
408 info
->int_size
= int_size
;
409 info
->long_size
= long_size
;
410 info
->pointer_size
= pointer_size
;
411 info
->size_t_size
= size_t_size
;
412 info
->alignment
= alignment
;
414 head
= g_hash_table_lookup(trace
->markers_hash
, (gconstpointer
)name
);
416 g_hash_table_insert(trace
->markers_hash
, (gpointer
)name
, info
);
418 g_hash_table_replace(trace
->markers_hash
, (gpointer
)name
, info
);
423 int allocate_marker_data(LttTrace
*trace
)
425 /* Init array to 0 */
426 trace
->markers
= g_array_sized_new(FALSE
, TRUE
,
427 sizeof(struct marker_info
), DEFAULT_MARKERS_NUM
);
430 trace
->markers_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
431 if (!trace
->markers_hash
)
436 void destroy_marker_data(LttTrace
*trace
)
439 struct marker_info
*info
;
441 for (i
=0; i
<trace
->markers
->len
; i
++) {
442 info
= &g_array_index(trace
->markers
, struct marker_info
, i
);
444 g_free(info
->format
);
446 g_array_free(info
->fields
, TRUE
);
448 g_array_free(trace
->markers
, TRUE
);
449 g_hash_table_destroy(trace
->markers_hash
);