From f104d082727461632e7a5cc1d2a854f0ad66db07 Mon Sep 17 00:00:00 2001 From: compudj Date: Fri, 16 Dec 2005 18:00:29 +0000 Subject: [PATCH] changes for genevent-new types git-svn-id: http://ltt.polymtl.ca/svn@1397 04897980-b3bd-0310-b5e0-8ef037075253 --- ltt/branches/poly/ltt/event.c | 275 +++++++++-- ltt/branches/poly/ltt/facility.c | 412 ++++++++++++----- ltt/branches/poly/ltt/ltt-private.h | 116 +++-- ltt/branches/poly/ltt/ltt.h | 29 +- ltt/branches/poly/ltt/parser.c | 451 +++++++++++------- ltt/branches/poly/ltt/parser.h | 45 +- ltt/branches/poly/ltt/tracefile.c | 684 ++++++++++++++++++++-------- 7 files changed, 1464 insertions(+), 548 deletions(-) diff --git a/ltt/branches/poly/ltt/event.c b/ltt/branches/poly/ltt/event.c index a5b04681..53a2b2ec 100644 --- a/ltt/branches/poly/ltt/event.c +++ b/ltt/branches/poly/ltt/event.c @@ -246,23 +246,20 @@ LttEventType *ltt_event_eventtype(const LttEvent *e) *Function name * ltt_event_field : get the root field of the event *Input params - * e : an instance of an event type + * e : an instance of an event type + * name : field name *Return value - * LttField * : the root field of the event + * LttField * : The requested field, or NULL ****************************************************************************/ -LttField *ltt_event_field(LttEvent *e) +LttField *ltt_event_field(LttEvent *e, GQuark name) { LttField * field; LttEventType * event_type = ltt_event_eventtype(e); if(unlikely(!event_type)) return NULL; - field = event_type->root_field; - if(unlikely(!field)) return NULL; - get_field_type_size(e->tracefile, event_type, 0, 0, - field, e->data); + return (LttField*)g_datalist_id_get_data(&event_type->fields_by_name, name); - return field; } /***************************************************************************** @@ -448,9 +445,8 @@ guint64 ltt_event_field_element_number(LttEvent *e, LttField *f) return 0; if(f->field_type->type_class == LTT_ARRAY) - return f->field_type->element_number; - return ltt_get_uint(LTT_GET_BO(e->tracefile), f->sequ_number_size, - e + f->offset_root); + return f->field_type->size; + return ltt_get_long_unsigned(e, &g_array_index(f->fields, LttField, 0)); } /***************************************************************************** @@ -458,20 +454,21 @@ guint64 ltt_event_field_element_number(LttEvent *e, LttField *f) * ltt_event_field_element_select * : Set the currently selected element for a sequence or * array field - * O(1) if fields are of fixed size, else O(n) if fields are - * of variable size. + * O(1) because of offset array. *Input params * e : an instance of an event type * f : a field of the instance * i : the ith element (0, ...) + *returns : the child field, at the right index, updated. ****************************************************************************/ -void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i) +LttField *ltt_event_field_element_select(LttEvent *e, LttField *f, gulong i) { - unsigned element_number; + gulong element_number; LttField *field; unsigned int k; size_t size; LttEventType *event_type; + off_t new_offset; if(f->field_type->type_class != LTT_ARRAY && f->field_type->type_class != LTT_SEQUENCE) @@ -482,27 +479,25 @@ void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i) /* Sanity check for i : 0..n-1 only, and must be lower or equal element_number */ if(i >= element_number) return; - - field = f->child[0]; - - if(f->field_type->type_class == LTT_SEQUENCE) - size = f->sequ_number_size; - else - size = 0; - - if(field->fixed_size == FIELD_FIXED) { - size += field->field_size * i; - - get_field_type_size(e->tracefile, event_type, - f->offset_root+size, size, field, e->data); + + if(f->field_type->type_class == LTT_ARRAY) { + field = &g_array_index(f->fields, LttField, 0); + } else { + field = &g_array_index(f->fields, LttField, 1); + } + if(field->field_size != 0) { + if(f->array_offset + (i * field->field_size) == field->offset_root) + return; /* fixed length child, already at the right offset */ + else + new_offset = f->array_offset + (i * field->field_size); } else { - for(k=0;k<=i;k++){ - size += get_field_type_size(e->tracefile, event_type, - f->offset_root+size, size, field, e->data); - } + /* Var. len. child */ + new_offset = g_array_index(f->dynamic_offsets, off_t, i); } - f->current_element = i; + compute_fields_offsets(e->tracefile, field, new_offset); + + return field; } /***************************************************************************** @@ -667,6 +662,21 @@ char *ltt_event_get_string(LttEvent *e, LttField *f) * data : a pointer to the event data. *Returns the field type size. ****************************************************************************/ + // TODO +// Change this function so it uses a *to offset value incrementation, just like +// genevent-new instead of returning a size. What is of interest here is the +// offset needed to read each field. +// +// Precomputed ones can be returned directly. Otherwise, the field is flagged +// "VARIABLE OFFSET" and must be computed dynamically. The dynamic processing +// of an offset takes the last known fixed offset, and then dynamically +// calculates all variable field offsets from it. +// +// After a VARIABLE SIZE element, all fields have a variable offset. +// Also, is an array or a sequence has variable length child, we must pass +// through all of them, saving the offsets in the dynamic_offsets array. + +#if 0 size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type, off_t offset_root, off_t offset_parent, LttField *field, void *data) @@ -674,6 +684,7 @@ size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type, size_t size = 0; guint i; LttType *type; + off_t align; g_assert(field->fixed_root != FIELD_UNKNOWN); g_assert(field->fixed_parent != FIELD_UNKNOWN); @@ -696,10 +707,16 @@ size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type, case LTT_SSIZE_T: case LTT_OFF_T: g_assert(field->fixed_size == FIELD_FIXED); - size = field->field_size; + size = field->field_size; + align = ltt_align(field->offset_root, + size, event_type->facility->has_alignment); + field->offset_root += align; + field->offset_parent += align; + size += align; break; case LTT_SEQUENCE: { + /* FIXME : check the type of sequence identifier */ gint seqnum = ltt_get_uint(LTT_GET_BO(tf), field->sequ_number_size, data + offset_root); @@ -782,5 +799,195 @@ size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type, return size; } +#endif //0 + + + + + +/***************************************************************************** + *Function name + * compute_fields_offsets : set the precomputable offset of the fields + *Input params + * tf : tracefile + * field : the field + * offset : pointer to the current offset, must be incremented + ****************************************************************************/ + + +void compute_fields_offsets(LttTracefile *tf, LttField *field, off_t *offset, + void *root) +{ + type = &field->field_type; + + switch(type->type_class) { + case LTT_INT_FIXED: + case LTT_UINT_FIXED: + case LTT_POINTER: + case LTT_CHAR: + case LTT_UCHAR: + case LTT_SHORT: + case LTT_USHORT: + case LTT_INT: + case LTT_UINT: + case LTT_LONG: + case LTT_ULONG: + case LTT_SIZE_T: + case LTT_SSIZE_T: + case LTT_OFF_T: + case LTT_FLOAT: + case LTT_ENUM: + if(field->fixed_root == FIELD_VARIABLE) { + /* Align offset on type size */ + *offset += ltt_align(*offset, get_alignment(tf, field), + tf->has_alignment); + /* remember offset */ + field->offset_root = *offset; + /* Increment offset */ + *offset += field->field_size; + } + /* None of these types has variable size, so we are sure that if + * this element has a fixed_root, then the following one will have + * a fixed root too, so it does not need the *offset at all. + */ + break; + case LTT_STRING: + if(field->fixed_root == FIELD_VARIABLE) { + field->offset_root = *offset; + } + *offset += strlen((gchar*)(root+*offset)) + 1; + break; + case LTT_ARRAY: + g_assert(type->fields->len == 1); + { + off_t local_offset; + LttField *child = &g_array_index(type->fields, LttField, 0); + if(field->fixed_root == FIELD_VARIABLE) { + *offset += ltt_align(*offset, get_alignment(tf, field), + tf->has_alignment); + /* remember offset */ + field->offset_root = *offset; + field->array_offset = *offset; + } + + if(field->field_size != 0) { + /* Increment offset */ + /* field_size is the array size in bytes */ + *offset = field->offset_root + field->field_size; + } else { + guint i; + *offset = field->array_offset; + field->dynamic_offsets = g_array_set_size(field->dynamic_offsets, + 0); + for(i=0; isize; i++) { + g_array_append_val(field->dynamic_offsets, *offset); + compute_fields_offsets(tf, child, offset); + } + } + // local_offset = field->array_offset; + // /* Set the offset at position 0 */ + // compute_fields_offsets(tf, child, &local_offset); + break; + case LTT_SEQUENCE: + g_assert(type->fields->len == 2); + { + off_t local_offset; + LttField *child; + guint i; + if(field->fixed_root == FIELD_VARIABLE) { + *offset += ltt_align(*offset, get_alignment(tf, field), + tf->has_alignment); + /* remember offset */ + field->offset_root = *offset; + + child = &g_array_index(type->fields, LttField, 0); + compute_fields_offsets(tf, child, offset); + child = &g_array_index(type->fields, LttField, 1); + *offset += ltt_align(*offset, get_alignment(tf, child), + tf->has_alignment); + field->array_offset = *offset; + + } else { + child = &g_array_index(type->fields, LttField, 1); + } + *offset = field->array_offset; + field->dynamic_offsets = g_array_set_size(field->dynamic_offsets, + 0); + for(i=0; ievent, field); i++) { + g_array_append_val(field->dynamic_offsets, *offset); + compute_fields_offsets(tf, child, offset); + } + // local_offset = field->array_offset; + // /* Set the offset at position 0 */ + // compute_fields_offsets(tf, child, &local_offset); + } + break; + case LTT_STRUCT: + { + LttField *child; + guint i; + gint ret=0; + if(field->fixed_root == FIELD_VARIABLE) { + *offset += ltt_align(*offset, get_alignment(tf, field), + tf->has_alignment); + /* remember offset */ + field->offset_root = *offset; + } else { + *offset = field->offset_root; + } + for(i=0; ifields->len; i++) { + child = &g_array_index(type->fields, LttField, i); + compute_fields_offsets(tf, child, offset); + } + } + break; + case LTT_UNION: + { + LttField *child; + guint i; + gint ret=0; + if(field->fixed_root == FIELD_VARIABLE) { + *offset += ltt_align(*offset, get_alignment(tf, field), + tf->has_alignment); + /* remember offset */ + field->offset_root = *offset; + } + for(i=0; ifields->len; i++) { + *offset = field->offset_root; + child = &g_array_index(type->fields, LttField, i); + compute_fields_offsets(tf, child, offset); + } + *offset = field->offset_root + field->field_size; + } + break; + case LTT_NONE: + default: + g_error("compute_fields_offsets : unknown type"); + } + +} +/***************************************************************************** + *Function name + * compute_offsets : set the dynamically computable offsets of an event type + *Input params + * tf : tracefile + * event : event type + * + ****************************************************************************/ +void compute_offsets(LttTracefile *tf, LttEventType *event, size_t *offset, + void *root) +{ + guint i; + gint ret; + + /* compute all variable offsets */ + for(i=0; ifields->len; i++) { + LttField *field = &g_array_index(event->fields, LttField, i); + ret = compute_fields_offsets(tf, field, offset, root); + if(ret) break; + } + +} + diff --git a/ltt/branches/poly/ltt/facility.c b/ltt/branches/poly/ltt/facility.c index f4c0acae..75b89bed 100644 --- a/ltt/branches/poly/ltt/facility.c +++ b/ltt/branches/poly/ltt/facility.c @@ -171,11 +171,9 @@ void generateFacility(LttFacility *f, facility_t *fac, guint32 checksum) { char * facilityName = fac->name; sequence_t * events = &fac->events; - int i; - //LttEventType * evType; - LttEventType * event_type; - LttField * field; + unsigned int i, j; LttType * type; + table_t *named_types = &fac->named_types; g_assert(f->name == g_quark_from_string(facilityName)); g_assert(f->checksum == checksum); @@ -190,56 +188,67 @@ void generateFacility(LttFacility *f, facility_t *fac, guint32 checksum) g_datalist_init(&f->events_by_name); g_datalist_init(&f->named_types); - - //f->named_types_number = fac->named_types.keys.position; - //f->named_types = g_array_sized_new (FALSE, TRUE, sizeof(LttType), - // fac->named_types.keys.position); - //f->named_types = g_new(LttType*, fac->named_types.keys.position); - //f->named_types = g_array_set_size(f->named_types, - // fac->named_types.keys.position); - - //for each event, construct field tree and type graph +#if 0 + /* The first day, he created the named types */ + + for(i=0; ikeys.position; i++) { + GQuark name = g_quark_from_string((char*)named_types->keys.array[i]); + type_descriptor_t *td = (type_descriptor_t*)named_types->values.array[i]; + + /* Create the type */ + type = g_new(LttType,1); + type->type_name = name; + type->type_class = td->type; + if(td->fmt) type->fmt = g_strdup(td->fmt); + else type->fmt = NULL; + type->size = td->size; + type->enum_strings = NULL; + type->element_type = NULL; + type->element_number = 0; + + construct_types_and_fields(type, td, NULL, NULL, ...); + + g_datalist_id_set_data_full(&fac->named_types, name, + type, (GDestroyNotify)freeLttNamedType); + + } +#endif //0 + /* The second day, he created the event fields and types */ + //for each event, construct field and type acyclic graph for(i=0;iposition;i++){ - event_type = &g_array_index(f->events, LttEventType, i); - //evType = g_new(LttEventType,1); - //f->events[i] = evType; + event_t parser_event = (event_t*)events->array[i]; + LttEventType *event_type = &g_array_index(f->events, LttEventType, i); event_type->name = - g_quark_from_string(((event_t*)(events->array[i]))->name); + g_quark_from_string(parser_event->name); g_datalist_id_set_data(&f->events_by_name, event_type->name, event_type); event_type->description = - g_strdup(((event_t*)(events->array[i]))->description); + g_strdup(parser_event->description); - field = g_new(LttField, 1); - event_type->root_field = field; - event_type->facility = f; event_type->index = i; + event_type->facility = f; - if(((event_t*)(events->array[i]))->type != NULL){ - // field->field_pos = 0; - type = lookup_named_type(f,((event_t*)(events->array[i]))->type); - field->field_type = type; - field->offset_root = 0; - field->fixed_root = FIELD_UNKNOWN; - field->offset_parent = 0; - field->fixed_parent = FIELD_UNKNOWN; - // field->base_address = NULL; - field->field_size = 0; - field->fixed_size = FIELD_UNKNOWN; - field->parent = NULL; - field->child = NULL; - field->current_element = 0; - - //construct field tree and type graph - construct_types_and_fields(f,((event_t*)(events->array[i]))->type,field); - }else{ - event_type->root_field = NULL; - g_free(field); + event_type->fields = g_array_sized_new(FALSE, TRUE, + sizeof(LttField), parser_event->fields.position); + event_type->fields = + g_array_set_size(event_type->fields, parser_event->fields.position); + g_datalist_init(&event_type->fields_by_name); + + for(j=0; jfields.position; j++) { + LttField *field = &g_array_index(event_type->fields, LttField, j); + field_t *parser_field = (field_t*)parser_event->fields.array[j]; + + construct_types_and_fields(NULL, NULL, field, parser_field, ...); + g_datalist_id_set_data(&event_type->fields_by_name, + field->name, + field); } - } + } + + /* What about 2 days weeks ? */ } @@ -249,11 +258,219 @@ void generateFacility(LttFacility *f, facility_t *fac, guint32 checksum) * internal recursion function *Input params * fac : facility struct - * td : type descriptor - * root_field : root field of the event + * field : destination lttv field + * fld : source parser field ****************************************************************************/ +//DONE +//make the change for arrays and sequences +//no more root field. -> change this for an array of fields. +// Compute the field size here. +// Flag fields as "VARIABLE OFFSET" or "FIXED OFFSET" : as soon as +// a field with a variable size is found, all the following fields must +// be flagged with "VARIABLE OFFSET", this will be done by the offset +// precomputation. + +void construct_fields(LttFacility *fac, + LttField *field, + field_t *fld) +{ + guint len; + type_descriptor_t *td; + + field->name = g_quark_from_string(fld->name); + if(fld->description) { + len = strlen(fld->description); + field->description = g_new(gchar, len+1); + strcpy(field->description, fld->description); + } + field->dynamic_offsets = NULL; + type = &field->field_type; + td = fld->type; + + type->enum_map = NULL; + type->fields = NULL; + type->fields_by_name = NULL; + + switch(td->type) { + case INT_FIXED: + type->type_class = LTT_INT_FIXED; + type->size = td->size; + break; + case UINT_FIXED: + type->type_class = LTT_UINT_FIXED; + type->size = td->size; + break; + case POINTER: + type->type_class = LTT_POINTER; + type->size = fac->pointer_size; + break; + case CHAR: + type->type_class = LTT_CHAR; + type->size = td->size; + break; + case UCHAR: + type->type_class = LTT_UCHAR; + type->size = td->size; + break; + case SHORT: + type->type_class = LTT_SHORT; + type->size = td->size; + break; + case USHORT: + type->type_class = LTT_USHORT; + type->size = td->size; + break; + case INT: + type->type_class = LTT_INT; + type->size = fac->int_size; + break; + case UINT: + type->type_class = LTT_UINT; + type->size = fac->int_size; + break; + case LONG: + type->type_class = LTT_LONG; + type->size = fac->long_size; + break; + case ULONG: + type->type_class = LTT_ULONG; + type->size = fac->long_size; + break; + case SIZE_T: + type->type_class = LTT_SIZE_T; + type->size = fac->size_t_size; + break; + case SSIZE_T: + type->type_class = LTT_SSIZE_T; + type->size = fac->size_t_size; + break; + case OFF_T: + type->type_class = LTT_OFF_T; + type->size = fac->size_t_size; + break; + case FLOAT: + type->type_class = LTT_FLOAT; + type->size = td->size; + break; + case STRING: + type->type_class = LTT_STRING; + type->size = 0; + break; + case ENUM: + type->type_class = LTT_ENUM; + type->size = fac->int_size; + { + guint i; + g_datalist_init(&type->enum_map); + for(i=0; ilabels.position; i++) { + GQuark key = g_quark_from_string((char*)td->labels.array[i]); + int *src = (int*)td->labels_values.array[i]; + /* it's always ok to cast a int to a pointer type */ + g_datalist_id_set_data(&type->enum_map, key, (gpointer)*src); + } + } + break; + case ARRAY: + type->type_class = LTT_ARRAY; + type->size = td->size; + type->fields = g_array_sized_new(FALSE, TRUE, sizeof(LttField), + td->fields.position); + type->fields = g_array_set_size(type->fields, td->fields.position); + { + guint i; + + for(i=0; ifields.position; i++) { + field_t *schild = (field_t*)td->fields.array[i]; + LttField *dchild = &g_array_index(type->fields, LttField, i); + + construct_fields(fac, dchild, schild); + } + } + break; + case SEQUENCE: + type->type_class = LTT_SEQUENCE; + type->size = 0; + type->fields = g_array_sized_new(FALSE, TRUE, sizeof(LttField), + td->fields.position); + type->fields = g_array_set_size(type->fields, td->fields.position); + { + guint i; + + for(i=0; ifields.position; i++) { + field_t *schild = (field_t*)td->fields.array[i]; + LttField *dchild = &g_array_index(type->fields, LttField, i); + + construct_fields(fac, dchild, schild); + } + } + break; + case STRUCT: + type->type_class = LTT_STRUCT; + type->size = 0; // Size not calculated by the parser. + type->fields = g_array_sized_new(FALSE, TRUE, sizeof(LttField), + td->fields.position); + type->fields = g_array_set_size(type->fields, td->fields.position); + g_datalist_init(&type->fields_by_name); + { + guint i; + + for(i=0; ifields.position; i++) { + field_t *schild = (field_t*)td->fields.array[i]; + LttField *dchild = &g_array_index(type->fields, LttField, i); + + construct_fields(fac, dchild, schild); + g_datalist_id_set_data(&type->fields_by_name, + dchild->name, + dchild); + } + } + break; + case UNION: + type->type_class = LTT_UNION; + type->size = 0; // Size not calculated by the parser. + type->fields = g_array_sized_new(FALSE, TRUE, sizeof(LttField), + td->fields.position); + type->fields = g_array_set_size(type->fields, td->fields.position); + g_datalist_init(&type->fields_by_name); + { + guint i; + + for(i=0; ifields.position; i++) { + field_t *schild = (field_t*)td->fields.array[i]; + LttField *dchild = &g_array_index(type->fields, LttField, i); + + construct_fields(fac, dchild, schild); + g_datalist_id_set_data(&type->fields_by_name, + dchild->name, + dchild); + } + } + break; + case NONE: + default: + g_error("construct_fields : unknown type"); + } + + field->field_size = type->size; + + /* Put the fields as "variable" offset to root first. Then, + * the offset precomputation will only have to set the FIELD_FIXED until + * it reaches the first variable length field, then stop. + */ + field->fixed_root = FIELD_VARIABLE; + + if(td->fmt) { + len = strlen(td->fmt); + type->fmt = g_new(gchar, len+1); + strcpy(type->fmt, td->fmt); + } +} + + + +#if 0 void construct_types_and_fields(LttFacility * fac, type_descriptor_t * td, LttField * fld) { @@ -349,7 +566,7 @@ void construct_types_and_fields(LttFacility * fac, type_descriptor_t * td, } - +#endif //0 #if 0 void construct_types_and_fields(LttFacility * fac, type_descriptor * td, @@ -433,29 +650,27 @@ void construct_types_and_fields(LttFacility * fac, type_descriptor * td, } #endif //0 +#if 0 /***************************************************************************** *Function name * lookup_named_type: search named type in the table * internal function *Input params * fac : facility struct - * td : type descriptor + * name : type name *Return value * : either find the named type, or create a new LttType ****************************************************************************/ -LttType * lookup_named_type(LttFacility *fac, type_descriptor_t * td) +LttType * lookup_named_type(LttFacility *fac, GQuark type_name) { LttType *type = NULL; - GQuark name = 0; - - if(td->type_name != NULL) { - /* Named type */ - name = g_quark_from_string(td->type_name); - - type = g_datalist_id_get_data(&fac->named_types, name); - } + /* Named type */ + type = g_datalist_id_get_data(&fac->named_types, name); + + g_assert(type != NULL); +#if 0 if(type == NULL){ /* Create the type */ type = g_new(LttType,1); @@ -472,9 +687,10 @@ LttType * lookup_named_type(LttFacility *fac, type_descriptor_t * td) g_datalist_id_set_data_full(&fac->named_types, name, type, (GDestroyNotify)freeLttNamedType); } +#endif //0 return type; } - +#endif //0 /***************************************************************************** *Function name @@ -505,71 +721,63 @@ void freeFacility(LttFacility * fac) } g_array_free(fac->events, TRUE); - g_datalist_clear(&fac->named_types); + g_datalist_clear(&fac->events_by_name); + // g_datalist_clear(&fac->named_types); } void freeEventtype(LttEventType * evType) { + unsigned int i; LttType * root_type; if(evType->description) - g_free(evType->description); - if(evType->root_field){ - root_type = evType->root_field->field_type; - freeLttField(evType->root_field); - freeLttType(&root_type); + g_free(evType->description); + + for(i=0; ifields->len;i++) { + freeLttType(&g_array_index(evType->fields, LttType, i)); } + g_array_free(evType->fields, TRUE); + g_datalist_clear(&evType->fields_by_name); +} + +void freeLttType(LttType * type) +{ + unsigned int i; + + if(type->fmt) + g_free(type->fmt); + + if(type->enum_map) + g_datalist_clear(&type->enum_map); + + if(type->fields) { + for(i=0; ifields->len; i++) { + freeLttField(&g_array_index(type->fields, LttField, i)); + } + g_array_free(type->fields, TRUE); + } + if(type->fields_by_name) + g_datalist_clear(&type->fields_by_name); } void freeLttNamedType(LttType * type) { - freeLttType(&type); + freeLttType(type); } -void freeLttType(LttType ** type) +void copy_enum_element(GQuark keyid, gpointer data, gpointer user_data) { - unsigned int i; - if(*type == NULL) return; - if((*type)->type_name != 0) return; //this is a named type. - //if((*type)->type_name){ - // return; //this is a named type - //} - if((*type)->fmt) - g_free((*type)->fmt); - if((*type)->enum_strings){ - g_free((*type)->enum_strings); - } + int *value = gpointer data; - if((*type)->element_type){ - for(i=0;i<(*type)->element_number;i++) - freeLttType(&((*type)->element_type[i])); - g_free((*type)->element_type); - } - g_free(*type); - *type = NULL; } -void freeLttField(LttField * fld) +void freeLttField(LttField * field) { - int i; - int size = 0; - - if(fld->field_type){ - if(fld->field_type->type_class == LTT_ARRAY || - fld->field_type->type_class == LTT_SEQUENCE){ - size = 1; - }else if(fld->field_type->type_class == LTT_STRUCT){ - size = fld->field_type->element_number; - } - } - - if(fld->child){ - for(i=0; ichild[i])freeLttField(fld->child[i]); - } - g_free(fld->child); - } - g_free(fld); + if(field->description) + g_free(field->description); + if(field->dynamic_offsets) + g_array_free(field->dynamic_offsets, TRUE); + freeLttType(field->type); } /***************************************************************************** diff --git a/ltt/branches/poly/ltt/ltt-private.h b/ltt/branches/poly/ltt/ltt-private.h index 666f1f33..03da264e 100644 --- a/ltt/branches/poly/ltt/ltt-private.h +++ b/ltt/branches/poly/ltt/ltt-private.h @@ -47,6 +47,8 @@ #define LTT_GET_FLOAT_BO(t) \ (((t)->float_word_order==__BYTE_ORDER)?0:1) +#define SEQUENCE_AVG_ELEMENTS 1000 + /* Hardcoded core events */ enum ltt_core_events { LTT_EVENT_FACILITY_LOAD, @@ -98,10 +100,11 @@ typedef guint64 uint64_t; struct LttFacilityLoad { guint32 checksum; guint32 id; + guint32 int_size; guint32 long_size; guint32 pointer_size; guint32 size_t_size; - guint32 alignment; + guint32 has_alignment; } LTT_PACKED_STRUCT; struct LttFacilityUnload { @@ -111,10 +114,11 @@ struct LttFacilityUnload { struct LttStateDumpFacilityLoad { guint32 checksum; guint32 id; + guint32 int_size; guint32 long_size; guint32 pointer_size; guint32 size_t_size; - guint32 alignment; + guint32 has_alignment; } LTT_PACKED_STRUCT; typedef struct _TimeHeartbeat { @@ -187,7 +191,7 @@ struct ltt_trace_header_0_4 { uint64_t start_freq; uint64_t start_tsc; uint64_t start_monotonic; - struct timespec start_time; + struct timeval start_time; } LTT_PACKED_STRUCT; @@ -209,23 +213,23 @@ struct ltt_block_start_header { struct _LttType{ - GQuark type_name; //type name if it is a named type - GQuark element_name; //elements name of the struct +// LTTV does not care about type names. Everything is a field. +// GQuark type_name; //type name if it is a named type gchar * fmt; - unsigned int size; + guint size; LttTypeEnum type_class; //which type - GQuark * enum_strings; //for enum labels - struct _LttType ** element_type; //for array, sequence and struct - unsigned element_number; //the number of elements - //for enum, array, sequence and structure + GData *enum_map; //maps enum labels to numbers. + GArray *fields; // Array of LttFields, for array, sequence, union, struct. + GData *fields_by_name; }; struct _LttEventType{ GQuark name; gchar * description; - guint index; //id of the event type within the facility + guint index; //id of the event type within the facility LttFacility * facility; //the facility that contains the event type - LttField * root_field; //root field + GArray * fields; //event's fields (LttField) + GData *fields_by_name; }; /* Structure LttEvent and LttEventPosition must begin with the _exact_ same @@ -274,65 +278,41 @@ struct _LttEventPosition{ enum field_status { FIELD_UNKNOWN, FIELD_VARIABLE, FIELD_FIXED }; struct _LttField{ - //guint field_pos; //field position within its parent - LttType * field_type; //field type, if it is root field - //then it must be struct type - - off_t offset_root; //offset from the root, -1:uninitialized - enum field_status fixed_root; //offset fixed according to the root - //-1:uninitialized, 0:unfixed, 1:fixed - off_t offset_parent; //offset from the parent,-1:uninitialized - enum field_status fixed_parent; //offset fixed according to its parent - //-1:uninitialized, 0:unfixed, 1:fixed - // void * base_address; //base address of the field ???? - - guint field_size; // //>0: size of the field, - // //0 : uncertain - // //-1: uninitialize - enum field_status fixed_size; - - /* for sequence */ - gint sequ_number_size; //the size of unsigned used to save the - //number of elements in the sequence - - gint element_size; //the element size of the sequence - //int field_fixed; //0: field has string or sequence - //1: field has no string or sequenc - //-1: uninitialize - - struct _LttField * parent; - struct _LttField ** child; //for array, sequence, struct and union: - //list of fields, it may have only one - //field if the element is not a struct or - //union - unsigned current_element; //which element is currently processed - // Used for sequences and arrays. + GQuark name; + gchar *description; + LttType field_type; //field type + + off_t offset_root; //offset from the root + enum field_status fixed_root; //offset fixed according to the root + + guint field_size; // size of the field + // Only if field type size is set to 0 + // (it's variable), then the field_size should be + // dynamically calculated while reading the trace + // and put here. Otherwise, the field_size always + // equels the type size. + off_t array_offset; // offset of the beginning of the array (for array + // and sequences) + GArray * dynamic_offsets; // array of offsets calculated dynamically at + // each event for sequences and arrays that + // contain variable length fields. }; - struct _LttFacility{ LttTrace *trace; - //gchar * name; //facility name GQuark name; guint32 checksum; //checksum of the facility guint32 id; //id of the facility - guint32 pointer_size; + guint32 int_size; guint32 long_size; + guint32 pointer_size; guint32 size_t_size; guint32 alignment; - - //LttEventType ** events; //array of event types - //unsigned int event_number; //number of events in the facility - //LttType ** named_types; - //unsigned int named_types_number; - GArray *events; GData *events_by_name; - // GArray *named_types; - //GData *named_types_by_name; - GData *named_types; + // not necessary in LTTV GData *named_types; unsigned char exists; /* 0 does not exist, 1 exists */ }; @@ -369,9 +349,11 @@ struct _LttTracefile{ int fd; //file descriptor off_t file_size; //file size //unsigned block_size; //block_size - unsigned int num_blocks; //number of blocks in the file + guint num_blocks; //number of blocks in the file gboolean reverse_bo; //must we reverse byte order ? gboolean float_word_order; //what is the byte order of floats ? + size_t has_alignment; //alignment of events in the tracefile. + // 0 or the architecture size in bytes. size_t buffer_header_size; @@ -412,7 +394,6 @@ struct _LttTrace{ guint8 ltt_minor_version; guint8 flight_recorder; guint8 has_heartbeat; - guint8 has_alignment; guint8 has_tsc; uint64_t start_freq; uint64_t start_tsc; @@ -454,4 +435,21 @@ struct _LttSystemDescription { //#define EVENT_HEADER_SIZE (TIMESTAMP_SIZE + EVENT_ID_SIZE) +/* Calculate the offset needed to align the type. + * If has_alignment is 0, alignment is disactivated. + * else, the function returns the offset needed to + * align align_drift on the has_alignment value (should be + * the size of the architecture). */ +static inline unsigned int ltt_align(size_t align_drift, + size_t size_of_type, + size_t has_alignment) +{ + size_t alignment = min(has_alignment, size_of_type); + + return ((alignment - align_drift) & (alignment-1)); +} + +off_t field_align(LttTracefile *tf, LttField *field, off_t offset); + + #endif /* LTT_PRIVATE_H */ diff --git a/ltt/branches/poly/ltt/ltt.h b/ltt/branches/poly/ltt/ltt.h index 02d937c2..e0c7a731 100644 --- a/ltt/branches/poly/ltt/ltt.h +++ b/ltt/branches/poly/ltt/ltt.h @@ -1,5 +1,6 @@ /* This file is part of the Linux Trace Toolkit trace reading library * Copyright (C) 2003-2004 Michel Dagenais + * 2005 Mathieu Desnoyers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -131,10 +132,28 @@ typedef enum _LttArchEndian } LttArchEndian; typedef enum _LttTypeEnum -{ LTT_INT, LTT_UINT, LTT_POINTER, LTT_LONG, LTT_ULONG, LTT_SIZE_T, - LTT_SSIZE_T, LTT_OFF_T, LTT_FLOAT, LTT_STRING, LTT_ENUM, LTT_ARRAY, - LTT_SEQUENCE, LTT_STRUCT, LTT_UNION +{ LTT_INT_FIXED, + LTT_UINT_FIXED, + LTT_POINTER, + LTT_CHAR, + LTT_UCHAR, + LTT_SHORT, + LTT_USHORT, + LTT_INT, + LTT_UINT, + LTT_LONG, + LTT_ULONG, + LTT_SIZE_T, + LTT_SSIZE_T, + LTT_OFF_T, + LTT_FLOAT, + LTT_STRING, + LTT_ENUM, + LTT_ARRAY, + LTT_SEQUENCE, + LTT_STRUCT, + LTT_UNION, + LTT_NONE } LttTypeEnum; - - + #endif // LTT_H diff --git a/ltt/branches/poly/ltt/parser.c b/ltt/branches/poly/ltt/parser.c index 795b3f96..23162992 100644 --- a/ltt/branches/poly/ltt/parser.c +++ b/ltt/branches/poly/ltt/parser.c @@ -3,14 +3,15 @@ parser.c: Generate helper declarations and functions to trace events from an event description file. -Copyright (C) 2002, Xianxiu Yang -Copyright (C) 2002, Michel Dagenais -This program is free software; you can redistribute it and/or modify + Copyright (C) 2005, Mathieu Desnoyers + Copyright (C) 2002, Xianxiu Yang + Copyright (C) 2002, Michel Dagenais + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. + the Free Software Foundation; version 2 of the License. -This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -43,15 +44,14 @@ This program is distributed in the hope that it will be useful, #include "parser.h" -static char *intOutputTypes[] = { - "int8_t", "int16_t", "int32_t", "int64_t", "short int", "int", "long int" }; +char *intOutputTypes[] = { + "int8_t", "int16_t", "int32_t", "int64_t" }; -static char *uintOutputTypes[] = { - "uint8_t", "uint16_t", "uint32_t", "uint64_t", "unsigned short int", - "unsigned int", "unsigned long int" }; +char *uintOutputTypes[] = { + "uint8_t", "uint16_t", "uint32_t", "uint64_t" }; -static char *floatOutputTypes[] = { - "undef", "undef", "float", "double", "undef", "float", "double" }; +char *floatOutputTypes[] = { + "undef", "undef", "float", "double" }; @@ -68,7 +68,7 @@ void strupper(char *string) } -int getSizeindex(int value) +int getSizeindex(unsigned int value) { switch(value) { case 1: @@ -94,21 +94,13 @@ int getSizeindex(int value) * size *****************************************************************************/ -int getSize(parse_file_t *in) +unsigned long long int getSize(parse_file_t *in) { char *token; token = getToken(in); if(in->type == NUMBER) { - if(strcmp(token,"1") == 0) return 0; - else if(strcmp(token,"2") == 0) return 1; - else if(strcmp(token,"4") == 0) return 2; - else if(strcmp(token,"8") == 0) return 3; - } - else if(in->type == NAME) { - if(strcmp(token,"short") == 0) return 4; - else if(strcmp(token,"medium") == 0) return 5; - else if(strcmp(token,"long") == 0) return 6; + return strtoull(token, NULL, 0); } in->error(in,"incorrect size specification"); return -1; @@ -183,13 +175,13 @@ char *allocAndCopy(char *str) * **************************************************************************/ -void getTypeAttributes(parse_file_t *in, type_descriptor_t *t) +void getTypeAttributes(parse_file_t *in, type_descriptor_t *t, + sequence_t * unnamed_types, table_t * named_types) { char * token; t->fmt = NULL; - t->size = -1; - t->alignment = 0; + t->size = 0; while(1) { token = getToken(in); @@ -210,9 +202,6 @@ void getTypeAttributes(parse_file_t *in, type_descriptor_t *t) } else if(!strcmp("size",token)) { getEqual(in); t->size = getSize(in); - } else if(!strcmp("align",token)) { - getEqual(in); - t->alignment = getNumber(in); } } } @@ -477,36 +466,62 @@ void parseEvent(parse_file_t *in, event_t * ev, sequence_t * unnamed_types, table_t * named_types) { char *token; + field_t *f; + sequence_init(&(ev->fields)); // getEventAttributes(in, ev); if(ev->name == NULL) in->error(in, "Event not named"); getRAnglebracket(in); - //... + //... ev->description = getDescription(in); - //event can have STRUCT, TYPEREF or NOTHING - getLAnglebracket(in); - - token = getToken(in); - if(in->type == FORWARDSLASH){ // NOTHING - ev->type = NULL; - }else if(in->type == NAME){ - if(strcmp("struct",token)==0 || strcmp("typeref",token)==0){ - ungetToken(in); - ev->type = parseType(in,NULL, unnamed_types, named_types); - if(ev->type->type != STRUCT && ev->type->type != NONE) - in->error(in,"type must be a struct"); - }else in->error(in, "not a valid type"); - - getLAnglebracket(in); - getForwardslash(in); - }else in->error(in,"not a struct type"); - - token = getName(in); - if(strcmp("event",token))in->error(in,"not an event definition"); - getRAnglebracket(in); // + int got_end = 0; + /* Events can have multiple fields. each field form at least a function + * parameter of the logging function. */ + while(!got_end) { + getLAnglebracket(in); + token = getToken(in); + + switch(in->type) { + case FORWARDSLASH: /* */ + token = getName(in); + if(strcmp("event",token))in->error(in,"not an event definition"); + getRAnglebracket(in); // + got_end = 1; + break; + case NAME: /* a field */ + if(strcmp("field",token))in->error(in,"expecting a field"); + f = (field_t *)memAlloc(sizeof(field_t)); + sequence_push(&(ev->fields),f); + parseFields(in, f, unnamed_types, named_types, 1); + break; + default: + in->error(in, "expecting or "); + break; + } + } +#if 0 + if(in->type == FORWARDSLASH){ // NOTHING + ev->type = NULL; + }else if(in->type == NAME){ + if(strcmp("struct",token)==0 || strcmp("typeref",token)==0){ + ungetToken(in); + ev->type = parseType(in,NULL, unnamed_types, named_types); + if(ev->type->type != STRUCT && ev->type->type != NONE) + in->error(in,"type must be a struct"); + }else in->error(in, "not a valid type"); + + getLAnglebracket(in); + getForwardslash(in); + }else in->error(in,"not a struct type"); + getLAnglebracket(in); + getForwardslash(in); + token = getName(in); + if(strcmp("event",token))in->error(in,"not an event definition"); + getRAnglebracket(in); // +#endif //0 } /***************************************************************************** @@ -514,37 +529,38 @@ void parseEvent(parse_file_t *in, event_t * ev, sequence_t * unnamed_types, * parseField : get field infomation from buffer *Input params * in : input file handle - * t : type descriptor + * f : field * unnamed_types : array of unamed types * named_types : array of named types + * tag : is field surrounded by a tag ? ****************************************************************************/ -void parseFields(parse_file_t *in, type_descriptor_t *t, +void parseFields(parse_file_t *in, field_t *f, sequence_t * unnamed_types, - table_t * named_types) + table_t * named_types, + int tag) { char * token; - field_t *f; - - f = (field_t *)memAlloc(sizeof(field_t)); - sequence_push(&(t->fields),f); - - // - getFieldAttributes(in, f); - if(f->name == NULL) in->error(in, "Field not named"); - getRAnglebracket(in); + if(tag) { + // + getFieldAttributes(in, f); + if(f->name == NULL) in->error(in, "Field not named"); + getRAnglebracket(in); - f->description = getDescription(in); + f->description = getDescription(in); + } // getLAnglebracket(in); f->type = parseType(in,NULL, unnamed_types, named_types); - getLAnglebracket(in); - getForwardslash(in); - token = getName(in); - if(strcmp("field",token))in->error(in,"not a valid field definition"); - getRAnglebracket(in); // + if(tag) { + getLAnglebracket(in); + getForwardslash(in); + token = getName(in); + if(strcmp("field",token))in->error(in,"not a valid field definition"); + getRAnglebracket(in); // + } } @@ -573,6 +589,7 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType, { char *token; type_descriptor_t *t; + field_t *f; if(inType == NULL) { t = (type_descriptor_t *) memAlloc(sizeof(type_descriptor_t)); @@ -587,13 +604,16 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType, if(strcmp(token,"struct") == 0) { t->type = STRUCT; - getTypeAttributes(in, t); + getTypeAttributes(in, t, unnamed_types, named_types); getRAnglebracket(in); // getLAnglebracket(in); // token = getToken(in); sequence_init(&(t->fields)); while(strcmp("field",token) == 0){ - parseFields(in,t, unnamed_types, named_types); + f = (field_t *)memAlloc(sizeof(field_t)); + sequence_push(&(t->fields),f); + + parseFields(in, f, unnamed_types, named_types, 1); //next field getLAnglebracket(in); @@ -607,15 +627,16 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType, } else if(strcmp(token,"union") == 0) { t->type = UNION; - getTypeAttributes(in, t); - if(t->size == -1) in->error(in, "Union has empty size"); - getRAnglebracket(in); // + getTypeAttributes(in, t, unnamed_types, named_types); + getRAnglebracket(in); // getLAnglebracket(in); // token = getToken(in); sequence_init(&(t->fields)); while(strcmp("field",token) == 0){ - parseFields(in,t, unnamed_types, named_types); + f = (field_t *)memAlloc(sizeof(field_t)); + sequence_push(&(t->fields),f); + parseFields(in, f, unnamed_types, named_types, 1); //next field getLAnglebracket(in); @@ -629,12 +650,20 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType, } else if(strcmp(token,"array") == 0) { t->type = ARRAY; - getTypeAttributes(in, t); - if(t->size == -1) in->error(in, "Array has empty size"); + sequence_init(&(t->fields)); + getTypeAttributes(in, t, unnamed_types, named_types); + if(t->size == 0) in->error(in, "Array has empty size"); + getForwardslash(in); getRAnglebracket(in); // - getLAnglebracket(in); // - t->nested_type = parseType(in, NULL, unnamed_types, named_types); + //getLAnglebracket(in); // + /* subfield */ + f = (field_t *)memAlloc(sizeof(field_t)); + sequence_push(&(t->fields),f); + parseFields(in, f, unnamed_types, named_types, 0); + + //getLAnglebracket(in); // + //t->nested_type = parseType(in, NULL, unnamed_types, named_types); getLAnglebracket(in); // getForwardslash(in); @@ -644,12 +673,44 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType, } else if(strcmp(token,"sequence") == 0) { t->type = SEQUENCE; - getTypeAttributes(in, t); - if(t->size == -1) in->error(in, "Sequence has empty size"); - getRAnglebracket(in); // - - getLAnglebracket(in); // - t->nested_type = parseType(in,NULL, unnamed_types, named_types); + sequence_init(&(t->fields)); + //getTypeAttributes(in, t, unnamed_types, named_types); + //getForwardslash(in); + getRAnglebracket(in); // + + //getLAnglebracket(in); // + /* subfield */ + f = (field_t *)memAlloc(sizeof(field_t)); + sequence_push(&(t->fields),f); + parseFields(in, f, unnamed_types, named_types, 0); + + //getLAnglebracket(in); // + /* subfield */ + f = (field_t *)memAlloc(sizeof(field_t)); + sequence_push(&(t->fields),f); + parseFields(in, f, unnamed_types, named_types, 0); + + //getLAnglebracket(in); // + //t->length_type = parseType(in, NULL, unnamed_types, named_types); + + //getLAnglebracket(in); // + + //t->nested_type = parseType(in, NULL, unnamed_types, named_types); + + if(t->fields.position < 1) in->error(in, "Sequence has no length type"); + if(t->fields.position < 2) in->error(in, "Sequence has no subtype"); + switch(((field_t*)t->fields.array[0])->type->type) { + case UINT_FIXED : + case UCHAR : + case USHORT : + case UINT : + case ULONG : + case SIZE_T : + case OFF_T : + break; + default: + in->error(in, "Wrong length type for sequence"); + } getLAnglebracket(in); // getForwardslash(in); @@ -658,30 +719,38 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType, getRAnglebracket(in); // } else if(strcmp(token,"enum") == 0) { - char * str, *str1; + char * str; + int value = -1; + t->type = ENUM; sequence_init(&(t->labels)); + sequence_init(&(t->labels_values)); sequence_init(&(t->labels_description)); t->already_printed = 0; - getTypeAttributes(in, t); - if(t->size == -1) in->error(in, "Sequence has empty size"); + getTypeAttributes(in, t, unnamed_types, named_types); + //if(t->size == 0) in->error(in, "Sequence has empty size"); + //Mathieu : we fix enum size to target int size. GCC is always like this. + //fox copy optimisation. + if(t->size != 0) in->error(in, "Enum has fixed size of target int."); + t->size = 0; getRAnglebracket(in); // } + else if(strcmp(token,"int_fixed") == 0) { + t->type = INT_FIXED; + getTypeAttributes(in, t, unnamed_types, named_types); + if(t->size == 0) in->error(in, "int has empty size"); + getForwardslash(in); + getRAnglebracket(in); + } + else if(strcmp(token,"uint_fixed") == 0) { + t->type = UINT_FIXED; + getTypeAttributes(in, t, unnamed_types, named_types); + if(t->size == 0) in->error(in, "uint has empty size"); + getForwardslash(in); + getRAnglebracket(in); + } + else if(strcmp(token,"char") == 0) { + t->type = CHAR; + t->size = 1; + getTypeAttributes(in, t, unnamed_types, named_types); + getForwardslash(in); + getRAnglebracket(in); + } + else if(strcmp(token,"uchar") == 0) { + t->type = UCHAR; + t->size = 1; + getTypeAttributes(in, t, unnamed_types, named_types); + getForwardslash(in); + getRAnglebracket(in); + } + else if(strcmp(token,"short") == 0) { + t->type = SHORT; + t->size = 2; + getTypeAttributes(in, t, unnamed_types, named_types); + getForwardslash(in); + getRAnglebracket(in); + } + else if(strcmp(token,"ushort") == 0) { + t->type = USHORT; + t->size = 2; + getTypeAttributes(in, t, unnamed_types, named_types); + getForwardslash(in); + getRAnglebracket(in); + } else if(strcmp(token,"int") == 0) { t->type = INT; - getTypeAttributes(in, t); - if(t->size == -1) in->error(in, "int has empty size"); + getTypeAttributes(in, t, unnamed_types, named_types); getForwardslash(in); getRAnglebracket(in); } else if(strcmp(token,"uint") == 0) { t->type = UINT; - getTypeAttributes(in, t); - if(t->size == -1) in->error(in, "uint has empty size"); + getTypeAttributes(in, t, unnamed_types, named_types); getForwardslash(in); getRAnglebracket(in); } + else if(strcmp(token,"pointer") == 0) { t->type = POINTER; - getTypeAttributes(in, t); + getTypeAttributes(in, t, unnamed_types, named_types); getForwardslash(in); getRAnglebracket(in); } else if(strcmp(token,"long") == 0) { t->type = LONG; - getTypeAttributes(in, t); + getTypeAttributes(in, t, unnamed_types, named_types); getForwardslash(in); getRAnglebracket(in); } else if(strcmp(token,"ulong") == 0) { t->type = ULONG; - getTypeAttributes(in, t); + getTypeAttributes(in, t, unnamed_types, named_types); getForwardslash(in); getRAnglebracket(in); } else if(strcmp(token,"size_t") == 0) { t->type = SIZE_T; - getTypeAttributes(in, t); + getTypeAttributes(in, t, unnamed_types, named_types); getForwardslash(in); getRAnglebracket(in); } else if(strcmp(token,"ssize_t") == 0) { t->type = SSIZE_T; - getTypeAttributes(in, t); + getTypeAttributes(in, t, unnamed_types, named_types); getForwardslash(in); getRAnglebracket(in); } else if(strcmp(token,"off_t") == 0) { t->type = OFF_T; - getTypeAttributes(in, t); + getTypeAttributes(in, t, unnamed_types, named_types); getForwardslash(in); getRAnglebracket(in); } else if(strcmp(token,"float") == 0) { t->type = FLOAT; - getTypeAttributes(in, t); + getTypeAttributes(in, t, unnamed_types, named_types); getForwardslash(in); getRAnglebracket(in); } else if(strcmp(token,"string") == 0) { t->type = STRING; - getTypeAttributes(in, t); + getTypeAttributes(in, t, unnamed_types, named_types); getForwardslash(in); getRAnglebracket(in); } else if(strcmp(token,"typeref") == 0){ // Must be a named type - if(inType != NULL) - in->error(in,"Named type cannot refer to a named type"); - else { - free(t); - sequence_pop(unnamed_types); - token = getNameAttribute(in); - t = find_named_type(token, named_types); - getForwardslash(in); // - getRAnglebracket(in); - return t; - } + free(t); + sequence_pop(unnamed_types); + token = getNameAttribute(in); + t = find_named_type(token, named_types); + if(t == NULL) in->error(in,"Named referred to must be pre-declared."); + getForwardslash(in); // + getRAnglebracket(in); + return t; }else in->error(in,"not a valid type"); return t; @@ -794,16 +901,22 @@ type_descriptor_t * find_named_type(char *name, table_t * named_types) type_descriptor_t *t; t = table_find(named_types,name); - if(t == NULL) { - t = (type_descriptor_t *)memAlloc(sizeof(type_descriptor_t)); - t->type_name = allocAndCopy(name); - t->type = NONE; - t->fmt = NULL; - table_insert(named_types,t->type_name,t); - // table_insert(named_types,allocAndCopy(name),t); - } + return t; -} +} + +type_descriptor_t * create_named_type(char *name, table_t * named_types) +{ + type_descriptor_t *t; + + t = (type_descriptor_t *)memAlloc(sizeof(type_descriptor_t)); + t->type_name = allocAndCopy(name); + t->type = NONE; + t->fmt = NULL; + table_insert(named_types,t->type_name,t); + // table_insert(named_types,allocAndCopy(name),t); + return t; +} /***************************************************************************** *Function name @@ -822,7 +935,7 @@ void parseTypeDefinition(parse_file_t * in, sequence_t * unnamed_types, token = getNameAttribute(in); if(token == NULL) in->error(in, "Type has empty name"); - t = find_named_type(token, named_types); + t = create_named_type(token, named_types); if(t->type != NONE) in->error(in,"redefinition of named type"); getRAnglebracket(in); // @@ -877,7 +990,10 @@ char *getForwardslash(parse_file_t * in) char *token; token = getToken(in); - if(in->type != FORWARDSLASH) in->error(in, "forward slash token was expected"); + //if(in->type != FORWARDSLASH) in->error(in, "forward slash token was expected"); + /* Mathieu : final / is optional now. */ + if(in->type != FORWARDSLASH) ungetToken(in); + return token; } @@ -1118,23 +1234,21 @@ void checkNamedTypesImplemented(table_t * named_types) ****************************************************************************/ void generateChecksum(char* facName, - unsigned long * checksum, sequence_t * events) + unsigned int * checksum, sequence_t * events) { unsigned long crc ; int pos; event_t * ev; - char str[256]; crc = crc32(facName); for(pos = 0; pos < events->position; pos++){ ev = (event_t *)(events->array[pos]); - crc = partial_crc32(ev->name,crc); - if(!ev->type) continue; //event without type - if(ev->type->type != STRUCT){ - sprintf(str,"event '%s' has a type other than STRUCT",ev->name); - error_callback(NULL, str); - } - crc = getTypeChecksum(crc, ev->type); + crc = partial_crc32(ev->name, crc); + for(unsigned int i = 0; i < ev->fields.position; i++) { + field_t *f = (field_t*)ev->fields.array[i]; + crc = partial_crc32(f->name, crc); + crc = getTypeChecksum(crc, f->type); + } } *checksum = crc; } @@ -1157,16 +1271,40 @@ unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type) field_t * fld; switch(type->type){ - case INT: - str = intOutputTypes[type->size]; + case INT_FIXED: + str = intOutputTypes[getSizeindex(type->size)]; break; - case UINT: - str = uintOutputTypes[type->size]; + case UINT_FIXED: + str = uintOutputTypes[getSizeindex(type->size)]; break; case POINTER: str = allocAndCopy("void *"); flag = 1; break; + case CHAR: + str = allocAndCopy("signed char"); + flag = 1; + break; + case UCHAR: + str = allocAndCopy("unsigned char"); + flag = 1; + break; + case SHORT: + str = allocAndCopy("short"); + flag = 1; + break; + case USHORT: + str = allocAndCopy("unsigned short"); + flag = 1; + break; + case INT: + str = allocAndCopy("int"); + flag = 1; + break; + case UINT: + str = allocAndCopy("uint"); + flag = 1; + break; case LONG: str = allocAndCopy("long"); flag = 1; @@ -1188,23 +1326,24 @@ unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type) flag = 1; break; case FLOAT: - str = floatOutputTypes[type->size]; + str = floatOutputTypes[getSizeindex(type->size)]; break; case STRING: str = allocAndCopy("string"); flag = 1; break; case ENUM: - str = appendString("enum ", uintOutputTypes[type->size]); + //str = appendString("enum ", uintOutputTypes[getSizeindex(type->size)]); + str = allocAndCopy("enum"); flag = 1; break; case ARRAY: - sprintf(buf,"%d",type->size); + sprintf(buf,"%zu", type->size); str = appendString("array ",buf); flag = 1; break; case SEQUENCE: - sprintf(buf,"%d",type->size); + sprintf(buf,"%zu", type->size); str = appendString("sequence ",buf); flag = 1; break; @@ -1226,9 +1365,12 @@ unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type) if(type->fmt) crc = partial_crc32(type->fmt,crc); - if(type->type == ARRAY || type->type == SEQUENCE){ - crc = getTypeChecksum(crc,type->nested_type); - }else if(type->type == STRUCT || type->type == UNION){ + if(type->type == ARRAY){ + crc = getTypeChecksum(crc,((field_t*)type->fields.array[0])->type); + } else if(type->type ==SEQUENCE) { + crc = getTypeChecksum(crc,((field_t*)type->fields.array[0])->type); + crc = getTypeChecksum(crc,((field_t*)type->fields.array[1])->type); + } else if(type->type == STRUCT || type->type == UNION){ for(pos =0; pos < type->fields.position; pos++){ fld = (field_t *) type->fields.array[pos]; crc = partial_crc32(fld->name,crc); @@ -1255,6 +1397,10 @@ void freeType(type_descriptor_t * tp) free(tp->labels.array[pos2]); } sequence_dispose(&(tp->labels)); + for(pos2 = 0; pos2 < tp->labels_values.position; pos2++) { + free(tp->labels_values.array[pos2]); + } + sequence_dispose(&(tp->labels_values)); } if(tp->type == STRUCT) { for(pos2 = 0; pos2 < tp->fields.position; pos2++) { @@ -1301,6 +1447,7 @@ void freeEvents(sequence_t *t) ev = (event_t *) t->array[pos]; free(ev->name); free(ev->description); + sequence_dispose(&ev->fields); free(ev); } diff --git a/ltt/branches/poly/ltt/parser.h b/ltt/branches/poly/ltt/parser.h index c846697b..21884fb6 100644 --- a/ltt/branches/poly/ltt/parser.h +++ b/ltt/branches/poly/ltt/parser.h @@ -77,9 +77,15 @@ static const int BUFFER_SIZE = 1024; /* Events data types */ typedef enum _data_type { + INT_FIXED, + UINT_FIXED, + POINTER, + CHAR, + UCHAR, + SHORT, + USHORT, INT, UINT, - POINTER, LONG, ULONG, SIZE_T, @@ -95,24 +101,21 @@ typedef enum _data_type { NONE } data_type_t; -/* Event type descriptors */ - typedef struct _type_descriptor { char * type_name; //used for named type data_type_t type; char *fmt; - int size; + size_t size; sequence_t labels; // for enumeration + sequence_t labels_values; // for enumeration sequence_t labels_description; int already_printed; - sequence_t fields; // for structure - struct _type_descriptor *nested_type; // for array and sequence - int alignment; + sequence_t fields; // for structure, array and sequence (field_t type) } type_descriptor_t; -/* Fields within types */ +/* Fields within types or events */ typedef struct _field{ char *name; char *description; @@ -125,7 +128,8 @@ typedef struct _field{ typedef struct _event { char *name; char *description; - type_descriptor_t *type; + //type_descriptor_t *type; + sequence_t fields; /* event fields */ int per_trace; /* Is the event able to be logged to a specific trace ? */ int per_tracefile; /* Must we log this event in a specific tracefile ? */ } event_t; @@ -135,11 +139,13 @@ typedef struct _facility { char * capname; char * description; sequence_t events; - sequence_t unnamed_types; + sequence_t unnamed_types; //FIXME : remove table_t named_types; + unsigned int checksum; } facility_t; -int getSize(parse_file_t *in); +int getSizeindex(unsigned int value); +unsigned long long int getSize(parse_file_t *in); unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type); void parseFacility(parse_file_t *in, facility_t * fac); @@ -149,12 +155,14 @@ void parseTypeDefinition(parse_file_t *in, sequence_t * unnamed_types, table_t * named_types); type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *t, sequence_t * unnamed_types, table_t * named_types); -void parseFields(parse_file_t *in, type_descriptor_t *t, - sequence_t * unnamed_types, table_t * named_types); +void parseFields(parse_file_t *in, field_t *f, + sequence_t * unnamed_types, + table_t * named_types, + int tag); void checkNamedTypesImplemented(table_t * namedTypes); type_descriptor_t * find_named_type(char *name, table_t * named_types); void generateChecksum(char * facName, - unsigned long * checksum, sequence_t * events); + unsigned int * checksum, sequence_t * events); /* get attributes */ @@ -206,4 +214,13 @@ crc32(const char *s) } +extern char *intOutputTypes[]; + +extern char *uintOutputTypes[]; + +extern char *floatOutputTypes[]; + + + + #endif // PARSER_H diff --git a/ltt/branches/poly/ltt/tracefile.c b/ltt/branches/poly/ltt/tracefile.c index cdfab23f..ec5152f3 100644 --- a/ltt/branches/poly/ltt/tracefile.c +++ b/ltt/branches/poly/ltt/tracefile.c @@ -78,16 +78,18 @@ GQuark LTT_TRACEFILE_NAME_FACILITIES; /* set the offset of the fields belonging to the event, need the information of the archecture */ -void set_fields_offsets(LttTracefile *tf, LttEventType *event_type); +//void set_fields_offsets(LttTracefile *tf, LttEventType *event_type); //size_t get_fields_offsets(LttTracefile *tf, LttEventType *event_type, void *data); /* get the size of the field type according to * The facility size information. */ +#if 0 static inline void preset_field_type_size(LttTracefile *tf, LttEventType *event_type, off_t offset_root, off_t offset_parent, enum field_status *fixed_root, enum field_status *fixed_parent, LttField *field); +#endif //0 /* map a fixed size or a block information from the file (fd) */ static gint map_block(LttTracefile * tf, guint block_num); @@ -179,6 +181,8 @@ static void parser_characters (GMarkupParseContext __UNUSED__ *context, des->description = g_strdup(text); } #endif //0 + + LttFacility *ltt_trace_get_facility_by_num(LttTrace *t, guint num) { @@ -213,6 +217,7 @@ int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t) /* Get float byte order : might be different from int byte order * (or is set to 0 if the trace has no float (kernel trace)) */ tf->float_word_order = any->float_word_order; + tf->has_alignment = any->has_alignment; if(t) { t->arch_type = ltt_get_uint32(LTT_GET_BO(tf), @@ -224,7 +229,6 @@ int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t) t->ltt_minor_version = any->minor_version; t->flight_recorder = any->flight_recorder; t->has_heartbeat = any->has_heartbeat; - t->has_alignment = any->has_alignment; t->has_tsc = any->has_tsc; } @@ -962,6 +966,8 @@ static int ltt_process_facility_tracefile(LttTracefile *tf) fac->id = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->id); fac->pointer_size = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->pointer_size); + fac->int_size = ltt_get_uint32(LTT_GET_BO(tf), + &fac_load_data->int_size); fac->long_size = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->long_size); fac->size_t_size = ltt_get_uint32(LTT_GET_BO(tf), @@ -977,7 +983,7 @@ static int ltt_process_facility_tracefile(LttTracefile *tf) /* Preset the field offsets */ for(i=0; ievents->len; i++){ et = &g_array_index(fac->events, LttEventType, i); - set_fields_offsets(tf, et); + precompute_offsets(tf, et); } fac->exists = 1; @@ -1016,6 +1022,8 @@ static int ltt_process_facility_tracefile(LttTracefile *tf) &fac_state_dump_load_data->id); fac->pointer_size = ltt_get_uint32(LTT_GET_BO(tf), &fac_state_dump_load_data->pointer_size); + fac->int_size = ltt_get_uint32(LTT_GET_BO(tf), + &fac_state_dump_load_data->int_size); fac->long_size = ltt_get_uint32(LTT_GET_BO(tf), &fac_state_dump_load_data->long_size); fac->size_t_size = ltt_get_uint32(LTT_GET_BO(tf), @@ -1030,7 +1038,7 @@ static int ltt_process_facility_tracefile(LttTracefile *tf) /* Preset the field offsets */ for(i=0; ievents->len; i++){ et = &g_array_index(fac->events, LttEventType, i); - set_fields_offsets(tf, et); + precompute_offsets(tf, et); } fac->exists = 1; @@ -1653,7 +1661,8 @@ int ltt_tracefile_read_update_event(LttTracefile *tf) /* Read event header */ - //TODO align + /* Align the head */ + pos += ltt_align(pos, tf->trace->arch_size, tf->has_alignment); if(tf->trace->has_tsc) { if(tf->trace->has_heartbeat) { @@ -1701,6 +1710,9 @@ int ltt_tracefile_read_update_event(LttTracefile *tf) event->event_size = ltt_get_uint16(LTT_GET_BO(tf), pos); pos += sizeof(guint16); + /* Align the head */ + pos += ltt_align(pos, tf->trace->arch_size, tf->has_alignment); + event->data = pos; /* get the data size and update the event fields with the current @@ -1834,7 +1846,7 @@ map_error: /* It will update the fields offsets too */ void ltt_update_event_size(LttTracefile *tf) { - ssize_t size = 0; + size_t size = 0; /* Specific handling of core events : necessary to read the facility control * tracefile. */ @@ -1889,12 +1901,9 @@ void ltt_update_event_size(LttTracefile *tf) g_quark_to_string(tf->name)); goto event_type_error; } - - if(event_type->root_field) - size = get_field_type_size(tf, event_type, - 0, 0, event_type->root_field, tf->event.data); - else - size = 0; + + /* Compute the dynamic offsets */ + compute_offsets(tf, event_type, &size, tf->event.data); //g_debug("Event root field : f.e %hhu.%hhu size %zd", // tf->event.facility_id, @@ -2003,7 +2012,7 @@ void setFieldsOffset(LttTracefile *tf, LttEventType *evT,void *evD) evT, 0,0,rootFld, evD); } #endif //0 - +#if 0 /***************************************************************************** *Function name * set_fields_offsets : set the precomputable offset of the fields @@ -2023,6 +2032,369 @@ void set_fields_offsets(LttTracefile *tf, LttEventType *event_type) field); } +#endif //0 + + +/***************************************************************************** + *Function name + * get_alignment : Get the alignment needed for a field. + *Input params + * tf : tracefile + * field : field + * + * returns : The size on which it must be aligned. + * + ****************************************************************************/ +off_t get_alignment(LttTracefile *tf, LttField *field) +{ + type = &field->field_type; + + switch(type->type_class) { + case LTT_INT_FIXED: + case LTT_UINT_FIXED: + case LTT_POINTER: + case LTT_CHAR: + case LTT_UCHAR: + case LTT_SHORT: + case LTT_USHORT: + case LTT_INT: + case LTT_UINT: + case LTT_LONG: + case LTT_ULONG: + case LTT_SIZE_T: + case LTT_SSIZE_T: + case LTT_OFF_T: + case LTT_FLOAT: + case LTT_ENUM: + /* Align offset on type size */ + return field->field_size; + break; + case LTT_STRING: + return 0; + break; + case LTT_ARRAY: + g_assert(type->fields->len == 1); + { + LttField *child = &g_array_index(type->fields, LttField, 0); + return get_alignment(tf, child); + } + break; + case LTT_SEQUENCE: + g_assert(type->fields->len == 2); + { + off_t localign = 0; + LttField *child = &g_array_index(type->fields, LttField, 0); + + localign = max(localign, get_alignment(tf, child)); + + child = &g_array_index(type->fields, LttField, 1); + localign = max(localign, get_alignment(tf, child)); + + return localign; + } + break; + case LTT_STRUCT: + case LTT_UNION: + { + guint i; + off_t localign = 0; + + for(i=0; ifields->len; i++) { + LttField *child = &g_array_index(type->fields, LttField, i); + localign = max(localign, get_alignment(tf, child)); + } + return localign; + } + break; + case LTT_NONE: + default: + g_error("get_alignment : unknown type"); + } + +} + +/***************************************************************************** + *Function name + * field_compute_static_size : Determine the size of fields known by their + * sole definition. Unions, arrays and struct sizes might be known, but + * the parser does not give that information. + *Input params + * tf : tracefile + * field : field + * + ****************************************************************************/ + +void field_compute_static_size(LttTracefile *tf, LttField *field) +{ + type = &field->field_type; + + switch(type->type_class) { + case LTT_INT_FIXED: + case LTT_UINT_FIXED: + case LTT_POINTER: + case LTT_CHAR: + case LTT_UCHAR: + case LTT_SHORT: + case LTT_USHORT: + case LTT_INT: + case LTT_UINT: + case LTT_LONG: + case LTT_ULONG: + case LTT_SIZE_T: + case LTT_SSIZE_T: + case LTT_OFF_T: + case LTT_FLOAT: + case LTT_ENUM: + case LTT_STRING: + /* nothing to do */ + break; + case LTT_ARRAY: + /* note this : array type size is the number of elements in the array, + * while array field size of the length of the array in bytes */ + g_assert(type->fields->len == 1); + { + LttField *child = &g_array_index(type->fields, LttField, 0); + field_compute_static_size(tf, child); + + if(child->field_size != 0) { + field->field_size = type->size * child->field_size; + field->dynamic_offsets = g_array_sized_new(FALSE, TRUE, + sizeof(off_t), type->size); + } else { + field->field_size = 0; + } + } + break; + case LTT_SEQUENCE: + g_assert(type->fields->len == 2); + { + local_offset = 0; + LttField *child = &g_array_index(type->fields, LttField, 1); + field_compute_static_size(tf, child); + field->field_size = 0; + type->size = 0; + if(child->field_size != 0) { + field->dynamic_offsets = g_array_sized_new(FALSE, TRUE, + sizeof(off_t), SEQUENCE_AVG_ELEMENTS); + } + } + break; + case LTT_STRUCT: + case LTT_UNION: + { + guint i; + for(i=0;ifields->len;i++) { + LttField *child = &g_array_index(type->fields, LttField, i); + field_compute_static_size(tf, child); + if(child->field_size != 0) { + type->size += ltt_align(type->size, get_alignment(tf, child), + tf->has_alignment); + type->size += child->field_size; + } else { + /* As soon as we find a child with variable size, we have + * a variable size */ + type->size = 0; + break; + } + } + field->field_size = type->size; + } + break; + default: + g_error("field_static_size : unknown type"); + +} + + + +/***************************************************************************** + *Function name + * precompute_fields_offsets : set the precomputable offset of the fields + *Input params + * tf : tracefile + * field : the field + * offset : pointer to the current offset, must be incremented + * + * return : 1 : found a variable length field, stop the processing. + * 0 otherwise. + ****************************************************************************/ + + +gint precompute_fields_offsets(LttTracefile *tf, LttField *field, off_t *offset) +{ + type = &field->field_type; + + switch(type->type_class) { + case LTT_INT_FIXED: + case LTT_UINT_FIXED: + case LTT_POINTER: + case LTT_CHAR: + case LTT_UCHAR: + case LTT_SHORT: + case LTT_USHORT: + case LTT_INT: + case LTT_UINT: + case LTT_LONG: + case LTT_ULONG: + case LTT_SIZE_T: + case LTT_SSIZE_T: + case LTT_OFF_T: + case LTT_FLOAT: + case LTT_ENUM: + /* Align offset on type size */ + *offset += ltt_align(*offset, get_alignment(tf, field), + tf->has_alignment); + /* remember offset */ + field->offset_root = *offset; + field->fixed_root = FIELD_FIXED; + /* Increment offset */ + *offset += field->field_size; + return 0; + break; + case LTT_STRING: + field->offset_root = *offset; + field->fixed_root = FIELD_FIXED; + return 1; + break; + case LTT_ARRAY: + g_assert(type->fields->len == 1); + { + LttField *child = &g_array_index(type->fields, LttField, 0); + + *offset += ltt_align(*offset, get_alignment(tf, field), + tf->has_alignment); + + /* remember offset */ + field->offset_root = *offset; + field->array_offset = *offset; + field->fixed_root = FIELD_FIXED; + + /* Let the child be variable */ + //precompute_fields_offsets(tf, child, offset); + + if(field->field_size != 0) { + /* Increment offset */ + /* field_size is the array size in bytes */ + *offset += field->field_size; + return 0; + } else { + return 1; + } + } + break; + case LTT_SEQUENCE: + g_assert(type->fields->len == 2); + { + LttField *child; + guint ret; + + *offset += ltt_align(*offset, get_alignment(tf, field), + tf->has_alignment); + + /* remember offset */ + field->offset_root = *offset; + field->fixed_root = FIELD_FIXED; + + child = &g_array_index(type->fields, LttField, 0); + ret = precompute_fields_offsets(tf, child, offset); + g_assert(ret == 0); /* Seq len cannot have variable len */ + + child = &g_array_index(type->fields, LttField, 1); + *offset += ltt_align(*offset, get_alignment(tf, child), + tf->has_alignment); + field->array_offset = *offset; + /* Set the offset position at position 0 */ + ret = precompute_fields_offsets(tf, child, offset); + + /* Cannot precompute fields offsets of sequence members, and has + * variable length. */ + return 1; + } + break; + case LTT_STRUCT: + { + LttField *child; + guint i; + gint ret=0; + + *offset += ltt_align(*offset, get_alignment(tf, field), + tf->has_alignment); + /* remember offset */ + field->offset_root = *offset; + field->fixed_root = FIELD_FIXED; + + for(i=0; i< type->fields->len; i++) { + child = &g_array_index(type->fields, LttField, i); + ret = precompute_fields_offsets(tf, child, offset); + + if(ret) break; + } + return ret; + } + break; + case LTT_UNION: + { + LttField *child; + guint i; + gint ret=0; + + *offset += ltt_align(*offset, get_alignment(tf, field), + tf->has_alignment); + /* remember offset */ + field->offset_root = *offset; + field->fixed_root = FIELD_FIXED; + + for(i=0; i< type->fields->len; i++) { + *offset = field->offset_root; + child = &g_array_index(type->fields, LttField, i); + ret = precompute_fields_offsets(tf, child, offset); + + if(ret) break; + } + *offset = field->offset_root + field->field_size; + return ret; + } + + break; + case LTT_NONE: + default: + g_error("precompute_fields_offsets : unknown type"); + return 1; + } + +} + + +/***************************************************************************** + *Function name + * precompute_offsets : set the precomputable offset of an event type + *Input params + * tf : tracefile + * event : event type + * + ****************************************************************************/ +void precompute_offsets(LttTracefile *tf, LttEventType *event) +{ + guint i; + off_t offset = 0; + gint ret; + + /* First, compute the size of fixed size fields. Will determine size for + * arrays, struct and unions, which is not done by the parser */ + for(i=0; ifields->len; i++) { + LttField *field = &g_array_index(event->fields, LttField, i); + field_compute_static_size(tf, field); + } + + /* Precompute all known offsets */ + for(i=0; ifields->len; i++) { + LttField *field = &g_array_index(event->fields, LttField, i); + ret = precompute_fields_offsets(tf, field, &offset); + if(ret) break; + } +} + + /***************************************************************************** @@ -2037,6 +2409,15 @@ void set_fields_offsets(LttTracefile *tf, LttEventType *event_type) * fixed_parent : Do we know a fixed offset to the parent ? * field : field ****************************************************************************/ + + + +// preset the fixed size offsets. Calculate them just like genevent-new : an +// increment of a *to value that represents the offset from the start of the +// event data. +// The preset information is : offsets up to (and including) the first element +// of variable size. All subsequent fields must be flagged "VARIABLE OFFSET". +#if 0 void preset_field_type_size(LttTracefile *tf, LttEventType *event_type, off_t offset_root, off_t offset_parent, enum field_status *fixed_root, enum field_status *fixed_parent, @@ -2184,7 +2565,7 @@ void preset_field_type_size(LttTracefile *tf, LttEventType *event_type, } } - +#endif //0 /***************************************************************************** *Function name @@ -2198,6 +2579,112 @@ void preset_field_type_size(LttTracefile *tf, LttEventType *event_type, *Returns : 0 if identical * 1 if not. ****************************************************************************/ +// this function checks for equality of field types. Therefore, it does not use +// per se offsets. For instance, an aligned version of a structure is +// compatible with an unaligned version of the same structure. +gint check_fields_compatibility(LttEventType *event_type1, + LttEventType *event_type2, + LttField *field1, LttField *field2) +{ + guint different = 0; + + if(field1 == NULL) { + if(field2 == NULL) goto end; + else { + different = 1; + goto end; + } + } else if(field2 == NULL) { + different = 1; + goto end; + } + + type1 = field1->field_type; + type2 = field2->field_type; + + if(type1->type_class != type2->type_class) { + different = 1; + goto end; + } + if(type1->element_name != type2->element_name) { + different = 1; + goto end; + } + + switch(type1->type_class) { + case LTT_INT_FIXED: + case LTT_UINT_FIXED: + case LTT_POINTER: + case LTT_CHAR: + case LTT_UCHAR: + case LTT_SHORT: + case LTT_USHORT: + case LTT_INT: + case LTT_UINT: + case LTT_LONG: + case LTT_ULONG: + case LTT_SIZE_T: + case LTT_SSIZE_T: + case LTT_OFF_T: + case LTT_FLOAT: + case LTT_ENUM: + if(field1->field_size != field2->field_size) + different = 1; + break; + case LTT_STRING: + break; + case LTT_ARRAY: + { + LttField *child1 = &g_array_index(type1->fields, LttField, 0); + LttField *child2 = &g_array_index(type2->fields, LttField, 0); + + if(type1->size != type2->size) + different = 1; + if(check_fields_compatibility(event_type1, event_type2, child1, child2)) + different = 1; + } + break; + case LTT_SEQUENCE: + { + LttField *child1 = &g_array_index(type1->fields, LttField, 1); + LttField *child2 = &g_array_index(type2->fields, LttField, 1); + + if(check_fields_compatibility(event_type1, event_type2, child1, child2)) + different = 1; + } + break; + case LTT_STRUCT: + case LTT_UNION: + { + LttField *child; + guint i; + + if(type1->fields->len != type2->fields->len) { + different = 1; + goto end; + } + + for(i=0; i< type1->fields->len; i++) { + child1 = &g_array_index(type1->fields, LttField, i); + child2 = &g_array_index(type2->fields, LttField, i); + different = check_fields_compatibility(event_type1, + event_type2, child1, child2); + + if(different) break; + } + } + break; + case LTT_NONE: + default: + g_error("precompute_fields_offsets : unknown type"); + } + +end: + return different; +} + + +#if 0 gint check_fields_compatibility(LttEventType *event_type1, LttEventType *event_type2, LttField *field1, LttField *field2) @@ -2310,176 +2797,9 @@ gint check_fields_compatibility(LttEventType *event_type1, end: return different; } - - - - -#if 0 -/***************************************************************************** - *Function name - * getFieldtypeSize: get the size of the field type (primitive type) - *Input params - * evT : event type - * offsetRoot : offset from the root - * offsetParent : offset from the parrent - * fld : field - * evD : event data, it may be NULL - *Return value - * int : size of the field - ****************************************************************************/ - -static inline gint getFieldtypeSize(LttTracefile *tf, - LttEventType * evT, gint offsetRoot, - gint offsetParent, LttField * fld, void *evD) -{ - gint size, size1, element_number, i, offset1, offset2; - LttType * type = fld->field_type; - - /* This likely has been tested with gcov : half of them.. */ - if(unlikely(fld->field_fixed == 1)){ - /* tested : none */ - if(unlikely(fld == evT->root_field)) { - size = fld->field_size; - goto end_getFieldtypeSize; - } - } - - /* From gcov profiling : half string, half struct, can we gain something - * from that ? (Mathieu) */ - switch(type->type_class) { - case LTT_ARRAY: - element_number = (int) type->element_number; - if(fld->field_fixed == -1){ - size = getFieldtypeSize(tf, evT, offsetRoot, - 0,fld->child[0], NULL); - if(size == 0){ //has string or sequence - fld->field_fixed = 0; - }else{ - fld->field_fixed = 1; - size *= element_number; - } - }else if(fld->field_fixed == 0){// has string or sequence - size = 0; - for(i=0;ichild[0], evD+size); - } - }else size = fld->field_size; - if(unlikely(!evD)){ - fld->fixed_root = (offsetRoot==-1) ? 0 : 1; - fld->fixed_parent = (offsetParent==-1) ? 0 : 1; - } - - break; - - case LTT_SEQUENCE: - size1 = (int) ltt_type_size(fac, type); - if(fld->field_fixed == -1){ - fld->sequ_number_size = size1; - fld->field_fixed = 0; - size = getFieldtypeSize(evT, offsetRoot, - 0,fld->child[0], NULL); - fld->element_size = size; - }else{//0: sequence - element_number = getIntNumber(tf,size1,evD); - type->element_number = element_number; - if(fld->element_size > 0){ - size = element_number * fld->element_size; - }else{//sequence has string or sequence - size = 0; - for(i=0;ichild[0], evD+size+size1); - } - } - size += size1; - } - if(unlikely(!evD)){ - fld->fixed_root = (offsetRoot==-1) ? 0 : 1; - fld->fixed_parent = (offsetParent==-1) ? 0 : 1; - } - - break; - - case LTT_STRING: - size = 0; - if(fld->field_fixed == -1){ - fld->field_fixed = 0; - }else{//0: string - /* Hope my implementation is faster than strlen (Mathieu) */ - char *ptr=(char*)evD; - size = 1; - /* from gcov : many many strings are empty, make it the common case.*/ - while(unlikely(*ptr != '\0')) { size++; ptr++; } - //size = ptr - (char*)evD + 1; //include end : '\0' - } - fld->fixed_root = (offsetRoot==-1) ? 0 : 1; - fld->fixed_parent = (offsetParent==-1) ? 0 : 1; - - break; - - case LTT_STRUCT: - element_number = (int) type->element_number; - size = 0; - /* tested with gcov */ - if(unlikely(fld->field_fixed == -1)){ - offset1 = offsetRoot; - offset2 = 0; - for(i=0;ichild[i], NULL); - if(likely(size1 > 0 && size >= 0)){ - size += size1; - if(likely(offset1 >= 0)) offset1 += size1; - offset2 += size1; - }else{ - size = -1; - offset1 = -1; - offset2 = -1; - } - } - if(unlikely(size == -1)){ - fld->field_fixed = 0; - size = 0; - }else fld->field_fixed = 1; - }else if(likely(fld->field_fixed == 0)){ - offset1 = offsetRoot; - offset2 = 0; - for(i=0;unlikely(ichild[i], evD+offset2); - offset1 += size; - offset2 += size; - } - size = offset2; - }else size = fld->field_size; - fld->fixed_root = (offsetRoot==-1) ? 0 : 1; - fld->fixed_parent = (offsetParent==-1) ? 0 : 1; - break; - - default: - if(unlikely(fld->field_fixed == -1)){ - size = (int) ltt_type_size(LTT_GET_BO(tf), type); - fld->field_fixed = 1; - }else size = fld->field_size; - if(unlikely(!evD)){ - fld->fixed_root = (offsetRoot==-1) ? 0 : 1; - fld->fixed_parent = (offsetParent==-1) ? 0 : 1; - } - break; - } - - fld->offset_root = offsetRoot; - fld->offset_parent = offsetParent; - fld->field_size = size; - -end_getFieldtypeSize: - - return size; -} #endif //0 + /***************************************************************************** *Function name * ltt_get_int : get an integer number -- 2.34.1