9cb9f1bcc6bf5adc5117ff4bba220c9a3bd9e219
3 genevent.c: Generate helper declarations and functions to trace events
4 from an event description file.
6 Copyright (C) 2002, Xianxiu Yang
7 Copyright (C) 2002, Michel Dagenais
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 /* This program reads the ".event" event definitions input files
24 specified as command line arguments and generates corresponding
25 ".c" and ".h" files required to trace such events in the kernel.
27 The program uses a very simple tokenizer, called from a hand written
28 recursive descent parser to fill a data structure describing the events.
29 The result is a sequence of events definitions which refer to type
32 A table of named types is maintained to allow refering to types by name
33 when the same type is used at several places. Finally a sequence of
34 all types is maintained to facilitate the freeing of all type
35 information when the processing of an ".event" file is finished. */
42 #include <linux/errno.h>
48 /* Named types may be referenced from anywhere */
52 int main(int argc
, char** argv
)
56 char buffer
[BUFFER_SIZE
];
60 printf("At least one event definition file is needed\n");
65 in
.error
= error_callback
;
67 for(i
= 1 ; i
< argc
; i
++) {
69 in
.name
= allocAndCopy(argv
[i
]);
71 in
.fp
= fopen(in
.name
, "r");
73 in
.error(&in
,"cannot open facility input file");
77 token
= getToken(&in
);
78 if(in
.type
== ENDFILE
) break;
80 if(strcmp(token
, "<")) in
.error(&in
,"not a facility file");
83 if(strcmp("facility",token
) == 0) {
84 fac
= memAlloc(sizeof(facility
));
86 fac
->description
= NULL
;
87 sequence_init(&(fac
->events
));
88 table_init(&(fac
->named_types
));
89 sequence_init(&(fac
->unnamed_types
));
91 parseFacility(&in
, fac
);
93 //check if any namedType is not defined
94 checkNamedTypesImplemented(&fac
->named_types
);
96 else in
.error(&in
,"facility token was expected");
98 generateFile(argv
[i
]);
101 free(fac
->description
);
102 freeEvents(&fac
->events
);
103 sequence_dispose(&fac
->events
);
104 freeNamedType(&fac
->named_types
);
105 table_dispose(&fac
->named_types
);
106 freeTypes(&fac
->unnamed_types
);
107 sequence_dispose(&fac
->unnamed_types
);
119 /*****************************************************************************
121 * generateFile : generate .c and .h file
123 * name : name of event definition file
124 ****************************************************************************/
125 void generateFile(char *name
){
126 char *loadName
, *hName
, *tmp
, *tmp2
;
129 unsigned long checksum
=0;
131 //remove .xml if it exists
132 tmp
= &name
[strlen(name
)-4];
133 if(strcmp(tmp
, ".xml") == 0){
137 tmp
= strrchr(name
,'/');
144 loadName
= appendString("ltt-facility-loader-", tmp
);
145 tmp2
= appendString(loadName
,".h");
148 hName
= appendString("ltt-facility-", tmp
);
149 tmp2
= appendString(hName
,".h");
152 lFp
= fopen(loadName
,"w");
154 printf("Cannot open the file : %s\n",loadName
);
158 hFp
= fopen(hName
,"w");
160 printf("Cannot open the file : %s\n",hName
);
167 generateChecksum(fac
->name
, &checksum
, &(fac
->events
));
169 /* generate .h file, event enumeration then structures and functions */
170 fprintf(hFp
, "#ifndef _LTT_FACILITY_%s_H_\n",fac
->capname
);
171 fprintf(hFp
, "#define _LTT_FACILITY_%s_H_\n\n",fac
->capname
);
172 generateEnumEvent(hFp
, fac
->name
, &nbEvent
, checksum
);
173 generateTypeDefs(hFp
);
174 generateStructFunc(hFp
, fac
->name
,checksum
);
175 fprintf(hFp
, "#endif //_LTT_FACILITY_%s_H_\n",fac
->capname
);
177 /* generate .h file, calls to register the facility at init time */
178 generateLoaderfile(lFp
,fac
->name
,nbEvent
,checksum
,fac
->capname
);
185 /*****************************************************************************
187 * generateEnumEvent : output event enum to .h file
189 * fp : file to be written to
190 * facName : name of facility
192 * nbEvent : number of events in the facility
193 ****************************************************************************/
194 void generateEnumEvent(FILE *fp
, char *facName
, int * nbEvent
, unsigned long checksum
) {
197 fprintf(fp
,"#include <linux/ltt-log.h>\n\n");
199 fprintf(fp
,"/**** facility handle ****/\n\n");
200 fprintf(fp
,"extern trace_facility_t ltt_facility_%s_%X;\n",facName
, checksum
);
201 fprintf(fp
,"extern trace_facility_t ltt_facility_%s;\n\n\n",facName
, checksum
);
203 fprintf(fp
,"/**** event type ****/\n\n");
204 fprintf(fp
,"enum %s_event {\n",facName
);
206 for(pos
= 0; pos
< fac
->events
.position
;pos
++) {
207 fprintf(fp
,"\t%s", ((event
*)(fac
->events
.array
[pos
]))->name
);
208 if(pos
!= fac
->events
.position
-1) fprintf(fp
,",\n");
210 fprintf(fp
,"\n};\n\n\n");
212 // fprintf(fp,"/**** number of events in the facility ****/\n\n");
213 // fprintf(fp,"int nbEvents_%s = %d;\n\n\n",facName, fac->events.position);
214 *nbEvent
= fac
->events
.position
;
218 /*****************************************************************************
220 * printStruct : Generic struct printing function
222 * fp : file to be written to
223 * len : number of fields
224 * array : array of field info
225 * name : basic struct name
226 * facName : name of facility
227 * whichTypeFirst : struct or array/sequence first
228 * hasStrSeq : string or sequence present?
229 * structCount : struct postfix
230 ****************************************************************************/
233 printStruct(FILE * fp
, int len
, void ** array
, char * name
, char * facName
,
234 int * whichTypeFirst
, int * hasStrSeq
, int * structCount
)
239 type_descriptor
* td
;
241 for (pos
= 0; pos
< len
; pos
++) {
242 fld
= (field
*)array
[pos
];
244 if( td
->type
!= STRING
&& td
->type
!= SEQUENCE
&&
246 if (*whichTypeFirst
== 0) {
247 *whichTypeFirst
= 1; //struct first
252 fprintf(fp
,"struct %s_%s",name
, facName
);
254 fprintf(fp
, "_%d {\n",++*structCount
);
259 fprintf(fp
, "\t%s %s; /* %s */\n",
260 getTypeStr(td
),fld
->name
,fld
->description
);
262 if (*whichTypeFirst
== 0) {
263 //string or sequence or array first
268 fprintf(fp
,"} __attribute__ ((packed));\n\n");
275 fprintf(fp
,"} __attribute__ ((packed));\n\n");
280 /*****************************************************************************
282 * generateHfile : Create the typedefs
284 * fp : file to be written to
285 ****************************************************************************/
287 generateTypeDefs(FILE * fp
)
291 fprintf(fp
, "/**** Basic Type Definitions ****/\n\n");
293 for (pos
= 0; pos
< fac
->named_types
.values
.position
; pos
++) {
294 type_descriptor
* type
=
295 (type_descriptor
*)fac
->named_types
.values
.array
[pos
];
296 printStruct(fp
, type
->fields
.position
, type
->fields
.array
,
297 "", type
->type_name
, &tmp
, &tmp
, NULL
);
298 fprintf(fp
, "typedef struct _%s %s;\n\n",
299 type
->type_name
, type
->type_name
);
304 /*****************************************************************************
306 * generateEnumDefinition: generate enum definition if it exists
308 * fp : file to be written to
310 ****************************************************************************/
311 void generateEnumDefinition(FILE * fp
, type_descriptor
* type
){
314 if(type
->already_printed
) return;
316 fprintf(fp
,"enum {\n");
317 for(pos
= 0; pos
< type
->labels
.position
; pos
++){
318 fprintf(fp
,"\t%s", type
->labels
.array
[pos
]);
319 if (pos
!= type
->labels
.position
- 1) fprintf(fp
,",");
320 if(type
->labels_description
.array
[pos
] != NULL
)
321 fprintf(fp
,"\t/* %s */\n",type
->labels_description
.array
[pos
]);
325 fprintf(fp
,"};\n\n\n");
327 type
->already_printed
= 1;
330 /*****************************************************************************
332 * generateStrucTFunc: output structure and function to .h file
334 * fp : file to be written to
335 * facName : name of facility
336 ****************************************************************************/
337 void generateStructFunc(FILE * fp
, char * facName
, unsigned long checksum
){
340 type_descriptor
* td
;
342 int hasStrSeq
, flag
, structCount
, seqCount
,strCount
, whichTypeFirst
=0;
344 for(pos
= 0; pos
< fac
->events
.position
; pos
++){
345 ev
= (event
*) fac
->events
.array
[pos
];
346 //yxx if(ev->nested)continue;
347 fprintf(fp
,"/**** structure and trace function for event: %s ****/\n\n",
349 if(ev
->type
== 0){ // event without type
350 fprintf(fp
,"static inline void trace_%s_%s(void){\n",facName
,ev
->name
);
351 fprintf(fp
,"\tltt_log_event(ltt_facility_%s_%X, %s, 0, NULL);\n",
352 facName
,checksum
,ev
->name
);
353 fprintf(fp
,"};\n\n\n");
357 //if fields contain enum, print out enum definition
358 //MD : fixed in generateEnumDefinition to do not print the same enum
360 for(pos1
= 0; pos1
< ev
->type
->fields
.position
; pos1
++){
361 fld
= (field
*)ev
->type
->fields
.array
[pos1
];
362 if(fld
->type
->type
== ENUM
) generateEnumDefinition(fp
, fld
->type
);
365 //default: no string, array or sequence in the event
370 //structure for kernel
371 printStruct(fp
, ev
->type
->fields
.position
, ev
->type
->fields
.array
,
372 ev
->name
, facName
, &whichTypeFirst
, &hasStrSeq
, &structCount
);
374 //trace function : function name and parameters
377 fprintf(fp
,"static inline void trace_%s_%s(",facName
,ev
->name
);
378 for(pos1
= 0; pos1
< ev
->type
->fields
.position
; pos1
++){
379 fld
= (field
*)ev
->type
->fields
.array
[pos1
];
381 if(td
->type
== ARRAY
){
382 fprintf(fp
,"%s * %s",getTypeStr(td
), fld
->name
);
383 }else if(td
->type
== STRING
){
384 fprintf(fp
,"short int strlength_%d, %s * %s",
385 ++strCount
, getTypeStr(td
), fld
->name
);
386 }else if(td
->type
== SEQUENCE
){
387 fprintf(fp
,"%s seqlength_%d, %s * %s",
388 uintOutputTypes
[td
->size
], ++seqCount
,getTypeStr(td
), fld
->name
);
389 }else fprintf(fp
,"%s %s",getTypeStr(td
), fld
->name
);
390 if(pos1
!= ev
->type
->fields
.position
- 1) fprintf(fp
,", ");
392 fprintf(fp
,")\n{\n");
394 //length of buffer : length of all structures
395 fprintf(fp
,"\tint length = ");
396 for(pos1
=0;pos1
<structCount
;pos1
++){
397 fprintf(fp
,"sizeof(struct %s_%s_%d)",ev
->name
, facName
,pos1
+1);
398 if(pos1
!= structCount
-1) fprintf(fp
," + ");
401 //length of buffer : length of all arrays, sequences and strings
405 for(pos1
= 0; pos1
< ev
->type
->fields
.position
; pos1
++){
406 fld
= (field
*)ev
->type
->fields
.array
[pos1
];
408 if(td
->type
== SEQUENCE
|| td
->type
==STRING
|| td
->type
==ARRAY
){
409 if(structCount
|| flag
> 0) fprintf(fp
," + ");
410 if(td
->type
== SEQUENCE
)
411 fprintf(fp
,"sizeof(%s) + sizeof(%s) * seqlength_%d",
412 uintOutputTypes
[td
->size
], getTypeStr(td
), ++seqCount
);
413 else if(td
->type
==STRING
) fprintf(fp
,"strlength_%d + 1", ++strCount
);
414 else if(td
->type
==ARRAY
)
415 fprintf(fp
,"sizeof(%s) * %d", getTypeStr(td
),td
->size
);
416 if(structCount
== 0) flag
= 1;
422 // MD no more need. fprintf(fp,"\tchar buff[buflength];\n");
423 // write directly to the channel
424 fprintf(fp
, "\tunsigned int index;\n");
425 fprintf(fp
, "\tstruct ltt_channel_struct *channel;\n");
426 fprintf(fp
, "\tstruct ltt_trace_struct *trace;\n");
427 fprintf(fp
, "\tunsigned long flags;\n");
428 fprintf(fp
, "\tstruct %s_%s_1* __1;\n\n", ev
->name
, facName
);
430 fprintf(fp
, "\tread_lock(<t_traces.traces_rwlock);\n\n");
432 "\tif(ltt_traces.num_active_traces == 0) goto unlock_traces;\n\n");
435 "\tindex = ltt_get_index_from_facility(ltt_facility_%s_%X,\n"\
437 facName
, checksum
, ev
->name
);
440 fprintf(fp
, "\t/* Disable interrupts. */\n");
441 fprintf(fp
, "\tlocal_irq_save(flags);\n\n");
444 fprintf(fp
, "\tlist_for_each_entry(trace, <t_traces.head, list) {\n");
445 fprintf(fp
, "\t\tif(!trace->active) goto skip_trace;\n\n");
447 fprintf(fp
, "\t\tunsigned int header_length = "
448 "ltt_get_event_header_size(trace);\n");
449 fprintf(fp
, "\t\tunsigned int event_length = header_length + length;\n");
451 /* Reserve the channel */
452 fprintf(fp
, "\t\tchannel = ltt_get_channel_from_index(trace, index);\n");
454 "\t\tvoid *buff = relay_reserve(channel->rchan, event_length);\n");
455 fprintf(fp
, "\t\tif(buff == NULL) {\n");
456 fprintf(fp
, "\t\t\t/* Buffer is full*/\n");
457 fprintf(fp
, "\t\t\tchannel->events_lost++;\n");
458 fprintf(fp
, "\t\t\tgoto commit_work;\n");
459 fprintf(fp
, "\t\t}\n");
461 /* Write the header */
463 fprintf(fp
, "\t\tltt_write_event_header(channel, buff, \n"
464 "\t\t\t\tltt_facility_%s_%X, %s, length);\n",
465 facName
, checksum
, ev
->name
);
468 //declare a char pointer if needed : starts at the end of the structs.
469 if(structCount
+ hasStrSeq
> 1) {
470 fprintf(fp
,"\t\tchar * ptr = (char*)buff + header_length");
471 for(pos1
=0;pos1
<structCount
;pos1
++){
472 fprintf(fp
," + sizeof(struct %s_%s_%d)",ev
->name
, facName
,pos1
+1);
474 if(structCount
+ hasStrSeq
> 1) fprintf(fp
,";\n");
477 // Declare an alias pointer of the struct type to the beginning
478 // of the reserved area, just after the event header.
479 fprintf(fp
, "\t\t__1 = (struct %s_%s_1 *)(buff + header_length);\n",
481 //allocate memory for new struct and initialize it
482 //if(whichTypeFirst == 1){ //struct first
483 //for(pos1=0;pos1<structCount;pos1++){
484 // if(pos1==0) fprintf(fp,
485 // "\tstruct %s_%s_1 * __1 = (struct %s_%s_1 *)buff;\n",
486 // ev->name, facName,ev->name, facName);
487 //MD disabled else fprintf(fp,
488 // "\tstruct %s_%s_%d __%d;\n",
489 // ev->name, facName,pos1+1,pos1+1);
491 //}else if(whichTypeFirst == 2){
492 // for(pos1=0;pos1<structCount;pos1++)
493 // fprintf(fp,"\tstruct %s_%s_%d __%d;\n",
494 // ev->name, facName,pos1+1,pos1+1);
498 if(structCount
) fprintf(fp
,"\t\t//initialize structs\n");
501 for(pos1
= 0; pos1
< ev
->type
->fields
.position
; pos1
++){
502 fld
= (field
*)ev
->type
->fields
.array
[pos1
];
504 if(td
->type
!= ARRAY
&& td
->type
!= SEQUENCE
&& td
->type
!= STRING
){
508 // if(structCount > 1) fprintf(fp,"\n");
510 fprintf(fp
, "\t\t__1->%s = %s;\n", fld
->name
, fld
->name
);
512 //if(structCount == 1 && whichTypeFirst == 1)
513 // fprintf(fp, "\t__1->%s = %s;\n",fld->name,fld->name );
515 // fprintf(fp, "\t__%d.%s = %s;\n",structCount ,fld->name,fld->name);
519 // if(structCount) fprintf(fp,"\n");
520 //set ptr to the end of first struct if needed;
521 //if(whichTypeFirst == 1 && structCount + hasStrSeq > 1){
522 // fprintf(fp,"\n\t//set ptr to the end of the first struct\n");
523 // fprintf(fp,"\tptr += sizeof(struct %s_%s_1);\n\n",ev->name, facName);
526 //copy struct, sequence and string to buffer
531 for(pos1
= 0; pos1
< ev
->type
->fields
.position
; pos1
++){
532 fld
= (field
*)ev
->type
->fields
.array
[pos1
];
534 // if(td->type != STRING && td->type != SEQUENCE && td->type != ARRAY){
535 // if(flag == 0) structCount++;
537 // if((structCount > 1 || whichTypeFirst == 2) && flag == 1){
538 // assert(0); // MD : disabled !
539 // fprintf(fp,"\t//copy struct to buffer\n");
540 // fprintf(fp,"\tmemcpy(ptr, &__%d, sizeof(struct %s_%s_%d));\n",
541 // structCount, ev->name, facName,structCount);
542 // fprintf(fp,"\tptr += sizeof(struct %s_%s_%d);\n\n",
543 // ev->name, facName,structCount);
546 //else if(td->type == SEQUENCE){
547 if(td
->type
== SEQUENCE
){
549 fprintf(fp
,"\t\t//copy sequence length and sequence to buffer\n");
550 fprintf(fp
,"\t\t*ptr = seqlength_%d;\n",++seqCount
);
551 fprintf(fp
,"\t\tptr += sizeof(%s);\n",uintOutputTypes
[td
->size
]);
552 fprintf(fp
,"\t\tmemcpy(ptr, %s, sizeof(%s) * seqlength_%d);\n",
553 fld
->name
, getTypeStr(td
), seqCount
);
554 fprintf(fp
,"\t\tptr += sizeof(%s) * seqlength_%d;\n\n",
555 getTypeStr(td
), seqCount
);
557 else if(td
->type
==STRING
){
559 fprintf(fp
,"\t\t//copy string to buffer\n");
560 fprintf(fp
,"\t\tif(strlength_%d > 0){\n",++strCount
);
561 fprintf(fp
,"\t\t\tmemcpy(ptr, %s, strlength_%d + 1);\n",
562 fld
->name
, strCount
);
563 fprintf(fp
,"\t\t\tptr += strlength_%d + 1;\n",strCount
);
564 fprintf(fp
,"\t\t}else{\n");
565 fprintf(fp
,"\t\t\t*ptr = '\\0';\n");
566 fprintf(fp
,"\t\t\tptr += 1;\n");
567 fprintf(fp
,"\t\t}\n\n");
568 }else if(td
->type
==ARRAY
){
570 fprintf(fp
,"\t//copy array to buffer\n");
571 fprintf(fp
,"\tmemcpy(ptr, %s, sizeof(%s) * %d);\n",
572 fld
->name
, getTypeStr(td
), td
->size
);
573 fprintf(fp
,"\tptr += sizeof(%s) * %d;\n\n", getTypeStr(td
), td
->size
);
576 if(structCount
+ seqCount
> 1) fprintf(fp
,"\n");
579 fprintf(fp
,"commit_work:\n");
581 fprintf(fp
, "\t\t/* Commit the work */\n");
582 fprintf(fp
, "\t\trelay_commit(channel->rchan, buff, event_length);\n");
584 /* End of traces iteration */
585 fprintf(fp
, "skip_trace:\n\n");
586 fprintf(fp
, "\t}\n\n");
588 fprintf(fp
, "\t/* Re-enable interrupts */\n");
589 fprintf(fp
, "\tlocal_irq_restore(flags);\n");
590 fprintf(fp
, "\tpreempt_check_resched();\n");
593 fprintf(fp
, "unlock_traces:\n");
594 fprintf(fp
, "\tread_unlock(<t_traces.traces_rwlock);\n");
595 //call trace function
596 //fprintf(fp,"\n\t//call trace function\n");
597 //fprintf(fp,"\tltt_log_event(ltt_facility_%s_%X, %s, bufLength, buff);\n",facName,checksum,ev->name);
598 fprintf(fp
,"};\n\n\n");
603 /*****************************************************************************
605 * getTypeStr : generate type string
607 * td : a type descriptor
609 * char * : type string
610 ****************************************************************************/
611 char * getTypeStr(type_descriptor
* td
){
612 type_descriptor
* t
;
616 return intOutputTypes
[td
->size
];
618 return uintOutputTypes
[td
->size
];
624 return "unsigned long";
632 return floatOutputTypes
[td
->size
];
636 return uintOutputTypes
[td
->size
];
642 return intOutputTypes
[t
->size
];
644 return uintOutputTypes
[t
->size
];
650 return "unsigned long";
658 return floatOutputTypes
[t
->size
];
662 return uintOutputTypes
[t
->size
];
664 error_callback(NULL
,"Nested struct is not supportted");
668 case STRUCT
: //for now we do not support nested struct
669 error_callback(NULL
,"Nested struct is not supportted");
672 error_callback(NULL
,"No type information");
678 /*****************************************************************************
680 * generateLoaderfile: generate a facility loaded .h file
682 * fp : file to be written to
683 * facName : name of facility
684 * nbEvent : number of events in the facility
685 * checksum : checksum for the facility
686 ****************************************************************************/
687 void generateLoaderfile(FILE * fp
, char * facName
, int nbEvent
, unsigned long checksum
, char *capname
){
688 fprintf(fp
, "#ifndef _LTT_FACILITY_LOADER_%s_H_\n",capname
);
689 fprintf(fp
, "#define _LTT_FACILITY_LOADER_%s_H_\n\n",capname
);
690 fprintf(fp
,"#include <linux/ltt-facilities.h>\n", facName
, checksum
);
691 fprintf(fp
,"#include <linux/module.h>\n\n", facName
, checksum
);
692 fprintf(fp
,"ltt_facility_t\tltt_facility_%s;\n", facName
, checksum
);
693 fprintf(fp
,"ltt_facility_t\tltt_facility_%s_%X;\n\n", facName
, checksum
);
695 fprintf(fp
,"EXPORT_SYMBOL(ltt_facility_%s);\n\n",facName
, checksum
);
696 fprintf(fp
,"EXPORT_SYMBOL(ltt_facility_%s_%X);\n\n",facName
, checksum
);
697 fprintf(fp
,"#define LTT_FACILITY_SYMBOL\t\t\t\tltt_facility_%s\n",
699 fprintf(fp
,"#define LTT_FACILITY_CHECKSUM_SYMBOL\t\t\t\tltt_facility_%s_%X\n",
701 fprintf(fp
,"#define LTT_FACILITY_CHECKSUM\t\t\t0x%X\n", checksum
);
702 fprintf(fp
,"#define LTT_FACILITY_NAME\t\t\t\t\t\"%s\"\n", facName
);
703 fprintf(fp
,"#define LTT_FACILITY_NUM_EVENTS\t\t%d\n\n", nbEvent
);
704 fprintf(fp
, "#endif //_LTT_FACILITY_LOADER_%s_H_\n",capname
);
This page took 0.045679 seconds and 4 git commands to generate.