]> git.cworth.org Git - apitrace/blob - common/trace_parser.cpp
Relocate tracing (dis/en)enablement.
[apitrace] / common / trace_parser.cpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * Copyright 2010 VMware, Inc.
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27
28 #include <assert.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "trace_file.hpp"
33 #include "trace_parser.hpp"
34
35
36 #define TRACE_VERBOSE 0
37
38
39 namespace trace {
40
41
42 Parser::Parser() {
43     file = NULL;
44     next_call_no = 0;
45     version = 0;
46     api = API_UNKNOWN;
47
48     glGetErrorSig = NULL;
49 }
50
51
52 Parser::~Parser() {
53     close();
54 }
55
56
57 bool Parser::open(const char *filename) {
58     assert(!file);
59     file = File::createForRead(filename);
60     if (!file) {
61         return false;
62     }
63
64     version = read_uint();
65     if (version > TRACE_VERSION) {
66         std::cerr << "error: unsupported trace format version " << version << "\n";
67         return false;
68     }
69     api = API_UNKNOWN;
70
71     return true;
72 }
73
74 template <typename Iter>
75 inline void
76 deleteAll(Iter begin, Iter end)
77 {
78     while (begin != end) {
79         delete *begin;
80         ++begin;
81     }
82 }
83
84 template <typename Container>
85 inline void
86 deleteAll(Container &c)
87 {
88     deleteAll(c.begin(), c.end());
89     c.clear();
90 }
91
92 void Parser::close(void) {
93     if (file) {
94         file->close();
95         delete file;
96         file = NULL;
97     }
98
99     deleteAll(calls);
100
101     // Delete all signature data.  Signatures are mere structures which don't
102     // own their own memory, so we need to destroy all data we created here.
103
104     for (FunctionMap::iterator it = functions.begin(); it != functions.end(); ++it) {
105         FunctionSigState *sig = *it;
106         if (sig) {
107             delete [] sig->name;
108             for (unsigned arg = 0; arg < sig->num_args; ++arg) {
109                 delete [] sig->arg_names[arg];
110             }
111             delete [] sig->arg_names;
112             delete sig;
113         }
114     }
115     functions.clear();
116
117     for (StructMap::iterator it = structs.begin(); it != structs.end(); ++it) {
118         StructSigState *sig = *it;
119         if (sig) {
120             delete [] sig->name;
121             for (unsigned member = 0; member < sig->num_members; ++member) {
122                 delete [] sig->member_names[member];
123             }
124             delete [] sig->member_names;
125             delete sig;
126         }
127     }
128     structs.clear();
129
130     for (EnumMap::iterator it = enums.begin(); it != enums.end(); ++it) {
131         EnumSigState *sig = *it;
132         if (sig) {
133             for (unsigned value = 0; value < sig->num_values; ++value) {
134                 delete [] sig->values[value].name;
135             }
136             delete [] sig->values;
137             delete sig;
138         }
139     }
140     enums.clear();
141     
142     for (BitmaskMap::iterator it = bitmasks.begin(); it != bitmasks.end(); ++it) {
143         BitmaskSigState *sig = *it;
144         if (sig) {
145             for (unsigned flag = 0; flag < sig->num_flags; ++flag) {
146                 delete [] sig->flags[flag].name;
147             }
148             delete [] sig->flags;
149             delete sig;
150         }
151     }
152     bitmasks.clear();
153
154     next_call_no = 0;
155 }
156
157
158 void Parser::getBookmark(ParseBookmark &bookmark) {
159     bookmark.offset = file->currentOffset();
160     bookmark.next_call_no = next_call_no;
161 }
162
163
164 void Parser::setBookmark(const ParseBookmark &bookmark) {
165     file->setCurrentOffset(bookmark.offset);
166     next_call_no = bookmark.next_call_no;
167     
168     // Simply ignore all pending calls
169     deleteAll(calls);
170 }
171
172
173 Call *Parser::parse_call(Mode mode) {
174     do {
175         Call *call;
176         int c = read_byte();
177         switch (c) {
178         case trace::EVENT_ENTER:
179             parse_enter(mode);
180             break;
181         case trace::EVENT_LEAVE:
182             call = parse_leave(mode);
183             adjust_call_flags(call);
184             return call;
185         default:
186             std::cerr << "error: unknown event " << c << "\n";
187             exit(1);
188         case -1:
189             if (!calls.empty()) {
190                 call = calls.front();
191                 call->flags |= CALL_FLAG_INCOMPLETE;
192                 calls.pop_front();
193                 adjust_call_flags(call);
194                 return call;
195             }
196             return NULL;
197         }
198     } while(true);
199 }
200
201
202 /**
203  * Helper function to lookup an ID in a vector, resizing the vector if it doesn't fit.
204  */
205 template<class T>
206 T *lookup(std::vector<T *> &map, size_t index) {
207     if (index >= map.size()) {
208         map.resize(index + 1);
209         return NULL;
210     } else {
211         return map[index];
212     }
213 }
214
215
216 Parser::FunctionSigFlags *
217 Parser::parse_function_sig(void) {
218     size_t id = read_uint();
219
220     FunctionSigState *sig = lookup(functions, id);
221
222     if (!sig) {
223         /* parse the signature */
224         sig = new FunctionSigState;
225         sig->id = id;
226         sig->name = read_string();
227         sig->num_args = read_uint();
228         const char **arg_names = new const char *[sig->num_args];
229         for (unsigned i = 0; i < sig->num_args; ++i) {
230             arg_names[i] = read_string();
231         }
232         sig->arg_names = arg_names;
233         sig->flags = lookupCallFlags(sig->name);
234         sig->offset = file->currentOffset();
235         functions[id] = sig;
236
237         /**
238          * Try to autodetect the API.
239          *
240          * XXX: Ideally we would allow to mix multiple APIs in a single trace,
241          * but as it stands today, retrace is done separately for each API.
242          */
243         if (api == API_UNKNOWN) {
244             const char *n = sig->name;
245             if ((n[0] == 'g' && n[1] == 'l' && n[2] == 'X') || // glX*
246                 (n[0] == 'w' && n[1] == 'g' && n[2] == 'l' && n[3] >= 'A' && n[3] <= 'Z') || // wgl[A-Z]*
247                 (n[0] == 'C' && n[1] == 'G' && n[2] == 'L')) { // CGL*
248                 api = trace::API_GL;
249             } else if (n[0] == 'e' && n[1] == 'g' && n[2] == 'l' && n[3] >= 'A' && n[3] <= 'Z') { // egl[A-Z]*
250                 api = trace::API_EGL;
251             } else if (n[0] == 'D' &&
252                        ((n[1] == 'i' && n[2] == 'r' && n[3] == 'e' && n[4] == 'c' && n[5] == 't') || // Direct*
253                         (n[1] == '3' && n[2] == 'D'))) { // D3D*
254                 api = trace::API_DX;
255             } else {
256                 /* TODO */
257             }
258         }
259
260         /**
261          * Note down the signature of special functions for future reference.
262          *
263          * NOTE: If the number of comparisons increases we should move this to a
264          * separate function and use bisection.
265          */
266         if (sig->num_args == 0 &&
267             strcmp(sig->name, "glGetError") == 0) {
268             glGetErrorSig = sig;
269         }
270
271     } else if (file->currentOffset() < sig->offset) {
272         /* skip over the signature */
273         skip_string(); /* name */
274         unsigned num_args = read_uint();
275         for (unsigned i = 0; i < num_args; ++i) {
276              skip_string(); /*arg_name*/
277         }
278     }
279
280     assert(sig);
281     return sig;
282 }
283
284
285 StructSig *Parser::parse_struct_sig() {
286     size_t id = read_uint();
287
288     StructSigState *sig = lookup(structs, id);
289
290     if (!sig) {
291         /* parse the signature */
292         sig = new StructSigState;
293         sig->id = id;
294         sig->name = read_string();
295         sig->num_members = read_uint();
296         const char **member_names = new const char *[sig->num_members];
297         for (unsigned i = 0; i < sig->num_members; ++i) {
298             member_names[i] = read_string();
299         }
300         sig->member_names = member_names;
301         sig->offset = file->currentOffset();
302         structs[id] = sig;
303     } else if (file->currentOffset() < sig->offset) {
304         /* skip over the signature */
305         skip_string(); /* name */
306         unsigned num_members = read_uint();
307         for (unsigned i = 0; i < num_members; ++i) {
308             skip_string(); /* member_name */
309         }
310     }
311
312     assert(sig);
313     return sig;
314 }
315
316
317 /*
318  * Old enum signatures would cover a single name/value only:
319  *
320  *   enum_sig = id name value
321  *            | id
322  */
323 EnumSig *Parser::parse_old_enum_sig() {
324     size_t id = read_uint();
325
326     EnumSigState *sig = lookup(enums, id);
327
328     if (!sig) {
329         /* parse the signature */
330         sig = new EnumSigState;
331         sig->id = id;
332         sig->num_values = 1;
333         EnumValue *values = new EnumValue[sig->num_values];
334         values->name = read_string();
335         values->value = read_sint();
336         sig->values = values;
337         sig->offset = file->currentOffset();
338         enums[id] = sig;
339     } else if (file->currentOffset() < sig->offset) {
340         /* skip over the signature */
341         skip_string(); /*name*/
342         scan_value();
343     }
344
345     assert(sig);
346     return sig;
347 }
348
349
350 EnumSig *Parser::parse_enum_sig() {
351     size_t id = read_uint();
352
353     EnumSigState *sig = lookup(enums, id);
354
355     if (!sig) {
356         /* parse the signature */
357         sig = new EnumSigState;
358         sig->id = id;
359         sig->num_values = read_uint();
360         EnumValue *values = new EnumValue[sig->num_values];
361         for (EnumValue *it = values; it != values + sig->num_values; ++it) {
362             it->name = read_string();
363             it->value = read_sint();
364         }
365         sig->values = values;
366         sig->offset = file->currentOffset();
367         enums[id] = sig;
368     } else if (file->currentOffset() < sig->offset) {
369         /* skip over the signature */
370         int num_values = read_uint();
371         for (int i = 0; i < num_values; ++i) {
372             skip_string(); /*name */
373             skip_sint(); /* value */
374         }
375     }
376
377     assert(sig);
378     return sig;
379 }
380
381
382 BitmaskSig *Parser::parse_bitmask_sig() {
383     size_t id = read_uint();
384
385     BitmaskSigState *sig = lookup(bitmasks, id);
386
387     if (!sig) {
388         /* parse the signature */
389         sig = new BitmaskSigState;
390         sig->id = id;
391         sig->num_flags = read_uint();
392         BitmaskFlag *flags = new BitmaskFlag[sig->num_flags];
393         for (BitmaskFlag *it = flags; it != flags + sig->num_flags; ++it) {
394             it->name = read_string();
395             it->value = read_uint();
396             if (it->value == 0 && it != flags) {
397                 std::cerr << "warning: bitmask " << it->name << " is zero but is not first flag\n";
398             }
399         }
400         sig->flags = flags;
401         sig->offset = file->currentOffset();
402         bitmasks[id] = sig;
403     } else if (file->currentOffset() < sig->offset) {
404         /* skip over the signature */
405         int num_flags = read_uint();
406         for (int i = 0; i < num_flags; ++i) {
407             skip_string(); /*name */
408             skip_uint(); /* value */
409         }
410     }
411
412     assert(sig);
413     return sig;
414 }
415
416
417 void Parser::parse_enter(Mode mode) {
418     unsigned thread_id;
419
420     if (version >= 4) {
421         thread_id = read_uint();
422     } else {
423         thread_id = 0;
424     }
425
426     FunctionSigFlags *sig = parse_function_sig();
427
428     Call *call = new Call(sig, sig->flags, thread_id);
429
430     call->no = next_call_no++;
431
432     if (parse_call_details(call, mode)) {
433         calls.push_back(call);
434     } else {
435         delete call;
436     }
437 }
438
439
440 Call *Parser::parse_leave(Mode mode) {
441     unsigned call_no = read_uint();
442     Call *call = NULL;
443     for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) {
444         if ((*it)->no == call_no) {
445             call = *it;
446             calls.erase(it);
447             break;
448         }
449     }
450     if (!call) {
451         return NULL;
452     }
453
454     if (parse_call_details(call, mode)) {
455         return call;
456     } else {
457         delete call;
458         return NULL;
459     }
460 }
461
462
463 bool Parser::parse_call_details(Call *call, Mode mode) {
464     do {
465         int c = read_byte();
466         switch (c) {
467         case trace::CALL_END:
468             return true;
469         case trace::CALL_ARG:
470             parse_arg(call, mode);
471             break;
472         case trace::CALL_RET:
473             call->ret = parse_value(mode);
474             break;
475         default:
476             std::cerr << "error: ("<<call->name()<< ") unknown call detail "
477                       << c << "\n";
478             exit(1);
479         case -1:
480             return false;
481         }
482     } while(true);
483 }
484
485
486 /**
487  * Make adjustments to this particular call flags.
488  *
489  * NOTE: This is called per-call so no string comparisons should be done here.
490  * All name comparisons should be done when the signature is parsed instead.
491  */
492 void Parser::adjust_call_flags(Call *call) {
493     // Mark glGetError() = GL_NO_ERROR as verbose
494     if (call->sig == glGetErrorSig &&
495         call->ret &&
496         call->ret->toSInt() == 0) {
497         call->flags |= CALL_FLAG_VERBOSE;
498     }
499 }
500
501 void Parser::parse_arg(Call *call, Mode mode) {
502     unsigned index = read_uint();
503     Value *value = parse_value(mode);
504     if (value) {
505         if (index >= call->args.size()) {
506             call->args.resize(index + 1);
507         }
508         call->args[index].value = value;
509     }
510 }
511
512
513 Value *Parser::parse_value(void) {
514     int c;
515     Value *value;
516     c = read_byte();
517     switch (c) {
518     case trace::TYPE_NULL:
519         value = new Null;
520         break;
521     case trace::TYPE_FALSE:
522         value = new Bool(false);
523         break;
524     case trace::TYPE_TRUE:
525         value = new Bool(true);
526         break;
527     case trace::TYPE_SINT:
528         value = parse_sint();
529         break;
530     case trace::TYPE_UINT:
531         value = parse_uint();
532         break;
533     case trace::TYPE_FLOAT:
534         value = parse_float();
535         break;
536     case trace::TYPE_DOUBLE:
537         value = parse_double();
538         break;
539     case trace::TYPE_STRING:
540         value = parse_string();
541         break;
542     case trace::TYPE_ENUM:
543         value = parse_enum();
544         break;
545     case trace::TYPE_BITMASK:
546         value = parse_bitmask();
547         break;
548     case trace::TYPE_ARRAY:
549         value = parse_array();
550         break;
551     case trace::TYPE_STRUCT:
552         value = parse_struct();
553         break;
554     case trace::TYPE_BLOB:
555         value = parse_blob();
556         break;
557     case trace::TYPE_OPAQUE:
558         value = parse_opaque();
559         break;
560     case trace::TYPE_REPR:
561         value = parse_repr();
562         break;
563     default:
564         std::cerr << "error: unknown type " << c << "\n";
565         exit(1);
566     case -1:
567         value = NULL;
568         break;
569     }
570 #if TRACE_VERBOSE
571     if (value) {
572         std::cerr << "\tVALUE " << value << "\n";
573     }
574 #endif
575     return value;
576 }
577
578
579 void Parser::scan_value(void) {
580     int c = read_byte();
581     switch (c) {
582     case trace::TYPE_NULL:
583     case trace::TYPE_FALSE:
584     case trace::TYPE_TRUE:
585         break;
586     case trace::TYPE_SINT:
587         scan_sint();
588         break;
589     case trace::TYPE_UINT:
590         scan_uint();
591         break;
592     case trace::TYPE_FLOAT:
593         scan_float();
594         break;
595     case trace::TYPE_DOUBLE:
596         scan_double();
597         break;
598     case trace::TYPE_STRING:
599         scan_string();
600         break;
601     case trace::TYPE_ENUM:
602         scan_enum();
603         break;
604     case trace::TYPE_BITMASK:
605         scan_bitmask();
606         break;
607     case trace::TYPE_ARRAY:
608         scan_array();
609         break;
610     case trace::TYPE_STRUCT:
611         scan_struct();
612         break;
613     case trace::TYPE_BLOB:
614         scan_blob();
615         break;
616     case trace::TYPE_OPAQUE:
617         scan_opaque();
618         break;
619     case trace::TYPE_REPR:
620         scan_repr();
621         break;
622     default:
623         std::cerr << "error: unknown type " << c << "\n";
624         exit(1);
625     case -1:
626         break;
627     }
628 }
629
630
631 Value *Parser::parse_sint() {
632     return new SInt(-(signed long long)read_uint());
633 }
634
635
636 void Parser::scan_sint() {
637     skip_uint();
638 }
639
640
641 Value *Parser::parse_uint() {
642     return new UInt(read_uint());
643 }
644
645
646 void Parser::scan_uint() {
647     skip_uint();
648 }
649
650
651 Value *Parser::parse_float() {
652     float value;
653     file->read(&value, sizeof value);
654     return new Float(value);
655 }
656
657
658 void Parser::scan_float() {
659     file->skip(sizeof(float));
660 }
661
662
663 Value *Parser::parse_double() {
664     double value;
665     file->read(&value, sizeof value);
666     return new Double(value);
667 }
668
669
670 void Parser::scan_double() {
671     file->skip(sizeof(double));
672 }
673
674
675 Value *Parser::parse_string() {
676     return new String(read_string());
677 }
678
679
680 void Parser::scan_string() {
681     skip_string();
682 }
683
684
685 Value *Parser::parse_enum() {
686     EnumSig *sig;
687     signed long long value;
688     if (version >= 3) {
689         sig = parse_enum_sig();
690         value = read_sint();
691     } else {
692         sig = parse_old_enum_sig();
693         assert(sig->num_values == 1);
694         value = sig->values->value;
695     }
696     return new Enum(sig, value);
697 }
698
699
700 void Parser::scan_enum() {
701     if (version >= 3) {
702         parse_enum_sig();
703         skip_sint();
704     } else {
705         parse_old_enum_sig();
706     }
707 }
708
709
710 Value *Parser::parse_bitmask() {
711     BitmaskSig *sig = parse_bitmask_sig();
712
713     unsigned long long value = read_uint();
714
715     return new Bitmask(sig, value);
716 }
717
718
719 void Parser::scan_bitmask() {
720     parse_bitmask_sig();
721     skip_uint(); /* value */
722 }
723
724
725 Value *Parser::parse_array(void) {
726     size_t len = read_uint();
727     Array *array = new Array(len);
728     for (size_t i = 0; i < len; ++i) {
729         array->values[i] = parse_value();
730     }
731     return array;
732 }
733
734
735 void Parser::scan_array(void) {
736     size_t len = read_uint();
737     for (size_t i = 0; i < len; ++i) {
738         scan_value();
739     }
740 }
741
742
743 Value *Parser::parse_blob(void) {
744     size_t size = read_uint();
745     Blob *blob = new Blob(size);
746     if (size) {
747         file->read(blob->buf, size);
748     }
749     return blob;
750 }
751
752
753 void Parser::scan_blob(void) {
754     size_t size = read_uint();
755     if (size) {
756         file->skip(size);
757     }
758 }
759
760
761 Value *Parser::parse_struct() {
762     StructSig *sig = parse_struct_sig();
763     Struct *value = new Struct(sig);
764
765     for (size_t i = 0; i < sig->num_members; ++i) {
766         value->members[i] = parse_value();
767     }
768
769     return value;
770 }
771
772
773 void Parser::scan_struct() {
774     StructSig *sig = parse_struct_sig();
775     for (size_t i = 0; i < sig->num_members; ++i) {
776         scan_value();
777     }
778 }
779
780
781 Value *Parser::parse_opaque() {
782     unsigned long long addr;
783     addr = read_uint();
784     return new Pointer(addr);
785 }
786
787
788 void Parser::scan_opaque() {
789     skip_uint();
790 }
791
792
793 Value *Parser::parse_repr() {
794     Value *humanValue = parse_value();
795     Value *machineValue = parse_value();
796     return new Repr(humanValue, machineValue);
797 }
798
799
800 void Parser::scan_repr() {
801     scan_value();
802     scan_value();
803 }
804
805
806 const char * Parser::read_string(void) {
807     size_t len = read_uint();
808     char * value = new char[len + 1];
809     if (len) {
810         file->read(value, len);
811     }
812     value[len] = 0;
813 #if TRACE_VERBOSE
814     std::cerr << "\tSTRING \"" << value << "\"\n";
815 #endif
816     return value;
817 }
818
819
820 void Parser::skip_string(void) {
821     size_t len = read_uint();
822     file->skip(len);
823 }
824
825
826 /*
827  * For the time being, a signed int is encoded as any other value, but we here parse
828  * it without the extra baggage of the Value class.
829  */
830 signed long long
831 Parser::read_sint(void) {
832     int c;
833     c = read_byte();
834     switch (c) {
835     case trace::TYPE_SINT:
836         return -(signed long long)read_uint();
837     case trace::TYPE_UINT:
838         return read_uint();
839     default:
840         std::cerr << "error: unexpected type " << c << "\n";
841         exit(1);
842     case -1:
843         return 0;
844     }
845 }
846
847 void
848 Parser::skip_sint(void) {
849     skip_byte();
850     skip_uint();
851 }
852
853 unsigned long long Parser::read_uint(void) {
854     unsigned long long value = 0;
855     int c;
856     unsigned shift = 0;
857     do {
858         c = file->getc();
859         if (c == -1) {
860             break;
861         }
862         value |= (unsigned long long)(c & 0x7f) << shift;
863         shift += 7;
864     } while(c & 0x80);
865 #if TRACE_VERBOSE
866     std::cerr << "\tUINT " << value << "\n";
867 #endif
868     return value;
869 }
870
871
872 void Parser::skip_uint(void) {
873     int c;
874     do {
875         c = file->getc();
876         if (c == -1) {
877             break;
878         }
879     } while(c & 0x80);
880 }
881
882
883 inline int Parser::read_byte(void) {
884     int c = file->getc();
885 #if TRACE_VERBOSE
886     if (c < 0)
887         std::cerr << "\tEOF" << "\n";
888     else
889         std::cerr << "\tBYTE 0x" << std::hex << c << std::dec << "\n";
890 #endif
891     return c;
892 }
893
894
895 inline void Parser::skip_byte(void) {
896     file->skip(1);
897 }
898
899
900 } /* namespace trace */