From 1184dc37d4cee465b9888fcec352c4ebe86d4246 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 20 Aug 2010 12:02:42 -0400 Subject: [PATCH] ltt traceread: fix offsets calculation, should be per tracefile Signed-off-by: Mathieu Desnoyers --- ltt/event.c | 106 +++++++++++++++++++++++++++++++-------------- ltt/event.h | 11 +++++ ltt/marker-field.h | 23 ++++++++-- ltt/marker.c | 39 ++++++++++++----- ltt/tracefile.c | 16 +++++-- 5 files changed, 145 insertions(+), 50 deletions(-) diff --git a/ltt/event.c b/ltt/event.c index 4297bf0c..3745d896 100644 --- a/ltt/event.c +++ b/ltt/event.c @@ -153,6 +153,8 @@ LttTracefile *ltt_event_position_tracefile(LttEventPosition *ep) guint32 ltt_event_get_unsigned(LttEvent *e, struct marker_field *f) { gboolean reverse_byte_order; + struct LttField *eventfield; + int offset, size; if(unlikely(f->attributes & LTT_ATTRIBUTE_NETWORK_BYTE_ORDER)) { reverse_byte_order = (g_ntohs(0x1) != 0x1); @@ -160,22 +162,25 @@ guint32 ltt_event_get_unsigned(LttEvent *e, struct marker_field *f) reverse_byte_order = LTT_GET_BO(e->tracefile); } - switch(f->size) { + eventfield = ltt_event_field(e, marker_field_get_index(f)); + offset = eventfield->offset; + size = eventfield->size; + switch(size) { case 1: { - guint8 x = *(guint8 *)(e->data + f->offset); - return (guint32) x; + guint8 x = *(guint8 *)(e->data + offset); + return (guint32) x; } break; case 2: - return (guint32)ltt_get_uint16(reverse_byte_order, e->data + f->offset); + return (guint32)ltt_get_uint16(reverse_byte_order, e->data + offset); break; case 4: - return (guint32)ltt_get_uint32(reverse_byte_order, e->data + f->offset); + return (guint32)ltt_get_uint32(reverse_byte_order, e->data + offset); break; case 8: default: - g_critical("ltt_event_get_unsigned : field size %li unknown", f->size); + g_critical("ltt_event_get_unsigned : field size %i unknown", size); return 0; break; } @@ -184,28 +189,34 @@ guint32 ltt_event_get_unsigned(LttEvent *e, struct marker_field *f) gint32 ltt_event_get_int(LttEvent *e, struct marker_field *f) { gboolean reverse_byte_order; + struct LttField *eventfield; + int offset, size; + if(unlikely(f->attributes & LTT_ATTRIBUTE_NETWORK_BYTE_ORDER)) { reverse_byte_order = (g_ntohs(0x1) != 0x1); } else { reverse_byte_order = LTT_GET_BO(e->tracefile); } - switch(f->size) { + eventfield = ltt_event_field(e, marker_field_get_index(f)); + offset = eventfield->offset; + size = eventfield->size; + switch(size) { case 1: { - gint8 x = *(gint8 *)(e->data + f->offset); - return (gint32) x; + gint8 x = *(gint8 *)(e->data + offset); + return (gint32) x; } break; case 2: - return (gint32)ltt_get_int16(reverse_byte_order, e->data + f->offset); + return (gint32)ltt_get_int16(reverse_byte_order, e->data + offset); break; case 4: - return (gint32)ltt_get_int32(reverse_byte_order, e->data + f->offset); + return (gint32)ltt_get_int32(reverse_byte_order, e->data + offset); break; case 8: default: - g_critical("ltt_event_get_int : field size %li unknown", f->size); + g_critical("ltt_event_get_int : field size %i unknown", size); return 0; break; } @@ -214,30 +225,36 @@ gint32 ltt_event_get_int(LttEvent *e, struct marker_field *f) guint64 ltt_event_get_long_unsigned(LttEvent *e, struct marker_field *f) { gboolean reverse_byte_order; + struct LttField *eventfield; + int offset, size; + if(unlikely(f->attributes & LTT_ATTRIBUTE_NETWORK_BYTE_ORDER)) { reverse_byte_order = (g_ntohs(0x1) != 0x1); } else { reverse_byte_order = LTT_GET_BO(e->tracefile); } - switch(f->size) { + eventfield = ltt_event_field(e, marker_field_get_index(f)); + offset = eventfield->offset; + size = eventfield->size; + switch(size) { case 1: { - guint8 x = *(guint8 *)(e->data + f->offset); - return (guint64) x; + guint8 x = *(guint8 *)(e->data + offset); + return (guint64) x; } break; case 2: - return (guint64)ltt_get_uint16(reverse_byte_order, e->data + f->offset); + return (guint64)ltt_get_uint16(reverse_byte_order, e->data + offset); break; case 4: - return (guint64)ltt_get_uint32(reverse_byte_order, e->data + f->offset); + return (guint64)ltt_get_uint32(reverse_byte_order, e->data + offset); break; case 8: - return ltt_get_uint64(reverse_byte_order, e->data + f->offset); + return ltt_get_uint64(reverse_byte_order, e->data + offset); break; default: - g_critical("ltt_event_get_long_unsigned : field size %li unknown", f->size); + g_critical("ltt_event_get_long_unsigned : field size %i unknown", size); return 0; break; } @@ -246,30 +263,36 @@ guint64 ltt_event_get_long_unsigned(LttEvent *e, struct marker_field *f) gint64 ltt_event_get_long_int(LttEvent *e, struct marker_field *f) { gboolean reverse_byte_order; + struct LttField *eventfield; + int offset, size; + if(unlikely(f->attributes & LTT_ATTRIBUTE_NETWORK_BYTE_ORDER)) { reverse_byte_order = (g_ntohs(0x1) != 0x1); } else { reverse_byte_order = LTT_GET_BO(e->tracefile); } - switch(f->size) { + eventfield = ltt_event_field(e, marker_field_get_index(f)); + offset = eventfield->offset; + size = eventfield->size; + switch(size) { case 1: { - gint8 x = *(gint8 *)(e->data + f->offset); + gint8 x = *(gint8 *)(e->data + offset); return (gint64) x; } break; case 2: - return (gint64)ltt_get_int16(reverse_byte_order, e->data + f->offset); + return (gint64)ltt_get_int16(reverse_byte_order, e->data + offset); break; case 4: - return (gint64)ltt_get_int32(reverse_byte_order, e->data + f->offset); + return (gint64)ltt_get_int32(reverse_byte_order, e->data + offset); break; case 8: - return ltt_get_int64(reverse_byte_order, e->data + f->offset); + return ltt_get_int64(reverse_byte_order, e->data + offset); break; default: - g_critical("ltt_event_get_long_int : field size %li unknown", f->size); + g_critical("ltt_event_get_long_int : field size %i unknown", size); return 0; break; } @@ -279,6 +302,9 @@ gint64 ltt_event_get_long_int(LttEvent *e, struct marker_field *f) float ltt_event_get_float(LttEvent *e, struct marker_field *f) { gboolean reverse_byte_order; + struct LttField *eventfield; + int offset, size; + if(unlikely(f->attributes & LTT_ATTRIBUTE_NETWORK_BYTE_ORDER)) { reverse_byte_order = (g_ntohs(0x1) != 0x1); } else { @@ -286,11 +312,14 @@ float ltt_event_get_float(LttEvent *e, struct marker_field *f) reverse_byte_order = LTT_GET_FLOAT_BO(e->tracefile); } - g_assert(f->field_type.type_class == LTT_FLOAT && f->size == 4); + eventfield = ltt_event_field(e, marker_field_get_index(f)); + offset = eventfield->offset; + size = eventfield->size; + g_assert(f->field_type.type_class == LTT_FLOAT && size == 4); - if(reverse_byte_order == 0) return *(float *)(e->data + f->offset); + if(reverse_byte_order == 0) return *(float *)(e->data + offset); else{ - void *ptr = e->data + f->offset; + void *ptr = e->data + offset; guint32 value = bswap_32(*(guint32*)ptr); return *(float*)&value; } @@ -299,6 +328,9 @@ float ltt_event_get_float(LttEvent *e, struct marker_field *f) double ltt_event_get_double(LttEvent *e, struct marker_field *f) { gboolean reverse_byte_order; + struct LttField *eventfield; + int offset, size; + if(unlikely(f->attributes & LTT_ATTRIBUTE_NETWORK_BYTE_ORDER)) { reverse_byte_order = (g_ntohs(0x1) != 0x1); } else { @@ -306,14 +338,17 @@ double ltt_event_get_double(LttEvent *e, struct marker_field *f) reverse_byte_order = LTT_GET_FLOAT_BO(e->tracefile); } - if(f->size == 4) + eventfield = ltt_event_field(e, marker_field_get_index(f)); + offset = eventfield->offset; + size = eventfield->size; + if(size == 4) return ltt_event_get_float(e, f); - g_assert(f->field_type.type_class == LTT_FLOAT && f->size == 8); + g_assert(f->field_type.type_class == LTT_FLOAT && size == 8); - if(reverse_byte_order == 0) return *(double *)(e->data + f->offset); + if(reverse_byte_order == 0) return *(double *)(e->data + offset); else { - void *ptr = e->data + f->offset; + void *ptr = e->data + offset; guint64 value = bswap_64(*(guint64*)ptr); return *(double*)&value; } @@ -326,11 +361,16 @@ double ltt_event_get_double(LttEvent *e, struct marker_field *f) ****************************************************************************/ gchar *ltt_event_get_string(LttEvent *e, struct marker_field *f) { + struct LttField *eventfield; + int offset; + g_assert(f->type == LTT_TYPE_STRING); //caused memory leaks //return (gchar*)g_strdup((gchar*)(e->data + f->offset)); - return (gchar*)(e->data + f->offset); + eventfield = ltt_event_field(e, marker_field_get_index(f)); + offset = eventfield->offset; + return (gchar*)(e->data + offset); } diff --git a/ltt/event.h b/ltt/event.h index 8293d15f..456f229e 100644 --- a/ltt/event.h +++ b/ltt/event.h @@ -10,6 +10,11 @@ struct marker_field; +struct LttField { + int offset; + int size; +}; + /* * Structure LttEvent and LttEventPosition must begin with the _exact_ same * fields in the exact same order. LttEventPosition is a parent of LttEvent. @@ -31,6 +36,7 @@ struct LttEvent { LttTime event_time; void *data; /* event data */ + GArray *fields_offsets; /* current field offsets table */ guint data_size; guint event_size; /* event_size field of the header : used to verify data_size from marker. */ @@ -108,4 +114,9 @@ static inline LttCycleCount ltt_event_cycle_count(const LttEvent *e) return e->tsc; } +static inline struct LttField *ltt_event_field(const LttEvent *e, int index) +{ + return &g_array_index(e->fields_offsets, struct LttField, index); +} + #endif //_LTT_EVENT_H diff --git a/ltt/marker-field.h b/ltt/marker-field.h index 252bd892..7092b92b 100644 --- a/ltt/marker-field.h +++ b/ltt/marker-field.h @@ -19,11 +19,18 @@ enum ltt_type { LTT_TYPE_NONE, }; +/* + * Fields "offset" and "size" below are only valid while the event is being + * read. They are also being shared with events of the same type coming from + * other per-cpu tracefiles. Therefore, the "LttEvent" fields_offsets offset and + * size should be used rather than these. + */ struct marker_field { GQuark name; enum ltt_type type; - unsigned long offset; /* offset in the event data */ - unsigned long size; + unsigned int index; /* Field index within the event */ + unsigned long _offset; /* offset in the event data, USED ONLY INTERNALLY BY LIB */ + unsigned long _size; /* size of field. USED ONLY INTERNALLY BY LIB */ unsigned long alignment; unsigned long attributes; int static_offset; /* boolean - private - is the field offset statically @@ -41,9 +48,17 @@ static inline enum ltt_type marker_field_get_type(struct marker_field *field) return field->type; } -static inline unsigned long marker_field_get_size(struct marker_field *field) +/* + * Returns 0 if size is not known statically. + */ +static inline long marker_field_get_size(struct marker_field *field) +{ + return field->_size; +} + +static inline unsigned int marker_field_get_index(struct marker_field *field) { - return field->size; + return field->index; } #endif //_LTT_MARKERS_FIELD_H diff --git a/ltt/marker.c b/ltt/marker.c index 07b5c08e..ade05e16 100644 --- a/ltt/marker.c +++ b/ltt/marker.c @@ -250,30 +250,31 @@ static inline long add_type(struct marker_info *info, field->name = g_quark_from_string(tmpname); } field->type = trace_type; + field->index = info->fields->len-1; field->fmt = g_string_new(field_fmt->str); switch (trace_type) { case LTT_TYPE_SIGNED_INT: case LTT_TYPE_UNSIGNED_INT: case LTT_TYPE_POINTER: - field->size = trace_size; + field->_size = trace_size; field->alignment = trace_size; info->largest_align = max((guint8)field->alignment, (guint8)info->largest_align); field->attributes = attributes; if (offset == -1) { - field->offset = -1; + field->_offset = -1; field->static_offset = 0; return -1; } else { - field->offset = offset + ltt_align(offset, field->alignment, + field->_offset = offset + ltt_align(offset, field->alignment, info->alignment); field->static_offset = 1; - return field->offset + trace_size; + return field->_offset + trace_size; } case LTT_TYPE_STRING: - field->offset = offset; - field->size = 0; /* Variable length, size is 0 */ + field->_offset = offset; + field->_size = 0; /* Variable length, size is 0 */ field->alignment = 1; if (offset == -1) field->static_offset = 0; @@ -296,7 +297,7 @@ long marker_update_fields_offsets(struct marker_info *info, const char *data) for (i = info->fields->len - 1; i >= 0; i--) { field = &g_array_index(info->fields, struct marker_field, i); if (field->static_offset) { - offset = field->offset; + offset = field->_offset; break; } } @@ -308,12 +309,12 @@ long marker_update_fields_offsets(struct marker_info *info, const char *data) case LTT_TYPE_SIGNED_INT: case LTT_TYPE_UNSIGNED_INT: case LTT_TYPE_POINTER: - field->offset = offset + ltt_align(offset, field->alignment, + field->_offset = offset + ltt_align(offset, field->alignment, info->alignment); - offset = field->offset + field->size; + offset = field->_offset + field->_size; break; case LTT_TYPE_STRING: - field->offset = offset; + field->_offset = offset; offset = offset + strlen(&data[offset]) + 1; // not aligning on pointer size, breaking genevent backward compatibility. break; @@ -325,6 +326,24 @@ long marker_update_fields_offsets(struct marker_info *info, const char *data) return offset; } +void marker_update_event_fields_offsets(GArray *fields_offsets, + struct marker_info *info) +{ + unsigned int i; + + g_array_set_size(fields_offsets, info->fields->len); + for (i = 0; i < info->fields->len; i++) { + struct marker_field *mfield = + &g_array_index(info->fields, struct marker_field, i); + struct LttField *eventfield = + &g_array_index(fields_offsets, struct LttField, i); + eventfield->offset = mfield->_offset; + eventfield->size = mfield->_size; + g_assert(eventfield->offset != -1); + g_assert(eventfield->size != -1); + } +} + static void format_parse(const char *fmt, struct marker_info *info) { char trace_size = 0, c_size = 0; /* diff --git a/ltt/tracefile.c b/ltt/tracefile.c index 54da7470..0d8a248e 100644 --- a/ltt/tracefile.c +++ b/ltt/tracefile.c @@ -55,6 +55,8 @@ /* from marker.c */ extern long marker_update_fields_offsets(struct marker_info *info, const char *data); +extern void marker_update_event_fields_offsets(GArray *fields_offsets, + struct marker_info *info); /* Tracefile names used in this file */ @@ -333,7 +335,13 @@ static gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf) perror("Cannot map block for tracefile"); goto close_file; } - + + /* Create fields offset table */ + tf->event.fields_offsets = g_array_sized_new(FALSE, FALSE, + sizeof(struct LttField), 1); + if (!tf->event.fields_offsets) + goto close_file; + return 0; /* Error */ @@ -376,6 +384,7 @@ static void ltt_tracefile_close(LttTracefile *t) close(t->fd); if (t->buf_index) g_array_free(t->buf_index, TRUE); + g_array_free(t->event.fields_offsets, TRUE); } /**************************************************************************** @@ -1593,8 +1602,9 @@ void ltt_update_event_size(LttTracefile *tf) if (info->size != -1) size = info->size; else - size = marker_update_fields_offsets(marker_get_info_from_id(tf->mdata, - tf->event.event_id), tf->event.data); + size = marker_update_fields_offsets(info, tf->event.data); + /* Update per-tracefile offsets */ + marker_update_event_fields_offsets(tf->event.fields_offsets, info); } tf->event.data_size = size; -- 2.34.1