]> git.cworth.org Git - apitrace/blob - common/trace_parser.cpp
f3aea7e7cf482f26f69e74432691bcefbb75ab1c
[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                        (n[0] == 'C' && n[1] == 'r' && n[2] == 'e' && n[3] == 'a' && n[4] == 't' && n[5] == 'e')) { // Create*
255                 api = trace::API_DX;
256             } else {
257                 /* TODO */
258             }
259         }
260
261         /**
262          * Note down the signature of special functions for future reference.
263          *
264          * NOTE: If the number of comparisons increases we should move this to a
265          * separate function and use bisection.
266          */
267         if (sig->num_args == 0 &&
268             strcmp(sig->name, "glGetError") == 0) {
269             glGetErrorSig = sig;
270         }
271
272     } else if (file->currentOffset() < sig->offset) {
273         /* skip over the signature */
274         skip_string(); /* name */
275         unsigned num_args = read_uint();
276         for (unsigned i = 0; i < num_args; ++i) {
277              skip_string(); /*arg_name*/
278         }
279     }
280
281     assert(sig);
282     return sig;
283 }
284
285
286 StructSig *Parser::parse_struct_sig() {
287     size_t id = read_uint();
288
289     StructSigState *sig = lookup(structs, id);
290
291     if (!sig) {
292         /* parse the signature */
293         sig = new StructSigState;
294         sig->id = id;
295         sig->name = read_string();
296         sig->num_members = read_uint();
297         const char **member_names = new const char *[sig->num_members];
298         for (unsigned i = 0; i < sig->num_members; ++i) {
299             member_names[i] = read_string();
300         }
301         sig->member_names = member_names;
302         sig->offset = file->currentOffset();
303         structs[id] = sig;
304     } else if (file->currentOffset() < sig->offset) {
305         /* skip over the signature */
306         skip_string(); /* name */
307         unsigned num_members = read_uint();
308         for (unsigned i = 0; i < num_members; ++i) {
309             skip_string(); /* member_name */
310         }
311     }
312
313     assert(sig);
314     return sig;
315 }
316
317
318 /*
319  * Old enum signatures would cover a single name/value only:
320  *
321  *   enum_sig = id name value
322  *            | id
323  */
324 EnumSig *Parser::parse_old_enum_sig() {
325     size_t id = read_uint();
326
327     EnumSigState *sig = lookup(enums, id);
328
329     if (!sig) {
330         /* parse the signature */
331         sig = new EnumSigState;
332         sig->id = id;
333         sig->num_values = 1;
334         EnumValue *values = new EnumValue[sig->num_values];
335         values->name = read_string();
336         values->value = read_sint();
337         sig->values = values;
338         sig->offset = file->currentOffset();
339         enums[id] = sig;
340     } else if (file->currentOffset() < sig->offset) {
341         /* skip over the signature */
342         skip_string(); /*name*/
343         scan_value();
344     }
345
346     assert(sig);
347     return sig;
348 }
349
350
351 EnumSig *Parser::parse_enum_sig() {
352     size_t id = read_uint();
353
354     EnumSigState *sig = lookup(enums, id);
355
356     if (!sig) {
357         /* parse the signature */
358         sig = new EnumSigState;
359         sig->id = id;
360         sig->num_values = read_uint();
361         EnumValue *values = new EnumValue[sig->num_values];
362         for (EnumValue *it = values; it != values + sig->num_values; ++it) {
363             it->name = read_string();
364             it->value = read_sint();
365         }
366         sig->values = values;
367         sig->offset = file->currentOffset();
368         enums[id] = sig;
369     } else if (file->currentOffset() < sig->offset) {
370         /* skip over the signature */
371         int num_values = read_uint();
372         for (int i = 0; i < num_values; ++i) {
373             skip_string(); /*name */
374             skip_sint(); /* value */
375         }
376     }
377
378     assert(sig);
379     return sig;
380 }
381
382
383 BitmaskSig *Parser::parse_bitmask_sig() {
384     size_t id = read_uint();
385
386     BitmaskSigState *sig = lookup(bitmasks, id);
387
388     if (!sig) {
389         /* parse the signature */
390         sig = new BitmaskSigState;
391         sig->id = id;
392         sig->num_flags = read_uint();
393         BitmaskFlag *flags = new BitmaskFlag[sig->num_flags];
394         for (BitmaskFlag *it = flags; it != flags + sig->num_flags; ++it) {
395             it->name = read_string();
396             it->value = read_uint();
397             if (it->value == 0 && it != flags) {
398                 std::cerr << "warning: bitmask " << it->name << " is zero but is not first flag\n";
399             }
400         }
401         sig->flags = flags;
402         sig->offset = file->currentOffset();
403         bitmasks[id] = sig;
404     } else if (file->currentOffset() < sig->offset) {
405         /* skip over the signature */
406         int num_flags = read_uint();
407         for (int i = 0; i < num_flags; ++i) {
408             skip_string(); /*name */
409             skip_uint(); /* value */
410         }
411     }
412
413     assert(sig);
414     return sig;
415 }
416
417
418 void Parser::parse_enter(Mode mode) {
419     unsigned thread_id;
420
421     if (version >= 4) {
422         thread_id = read_uint();
423     } else {
424         thread_id = 0;
425     }
426
427     FunctionSigFlags *sig = parse_function_sig();
428
429     Call *call = new Call(sig, sig->flags, thread_id);
430
431     call->no = next_call_no++;
432
433     if (parse_call_details(call, mode)) {
434         calls.push_back(call);
435     } else {
436         delete call;
437     }
438 }
439
440
441 Call *Parser::parse_leave(Mode mode) {
442     unsigned call_no = read_uint();
443     Call *call = NULL;
444     for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) {
445         if ((*it)->no == call_no) {
446             call = *it;
447             calls.erase(it);
448             break;
449         }
450     }
451     if (!call) {
452         return NULL;
453     }
454
455     if (parse_call_details(call, mode)) {
456         return call;
457     } else {
458         delete call;
459         return NULL;
460     }
461 }
462
463
464 bool Parser::parse_call_details(Call *call, Mode mode) {
465     do {
466         int c = read_byte();
467         switch (c) {
468         case trace::CALL_END:
469             return true;
470         case trace::CALL_ARG:
471             parse_arg(call, mode);
472             break;
473         case trace::CALL_RET:
474             call->ret = parse_value(mode);
475             break;
476         default:
477             std::cerr << "error: ("<<call->name()<< ") unknown call detail "
478                       << c << "\n";
479             exit(1);
480         case -1:
481             return false;
482         }
483     } while(true);
484 }
485
486
487 /**
488  * Make adjustments to this particular call flags.
489  *
490  * NOTE: This is called per-call so no string comparisons should be done here.
491  * All name comparisons should be done when the signature is parsed instead.
492  */
493 void Parser::adjust_call_flags(Call *call) {
494     // Mark glGetError() = GL_NO_ERROR as verbose
495     if (call->sig == glGetErrorSig &&
496         call->ret &&
497         call->ret->toSInt() == 0) {
498         call->flags |= CALL_FLAG_VERBOSE;
499     }
500 }
501
502 void Parser::parse_arg(Call *call, Mode mode) {
503     unsigned index = read_uint();
504     Value *value = parse_value(mode);
505     if (value) {
506         if (index >= call->args.size()) {
507             call->args.resize(index + 1);
508         }
509         call->args[index].value = value;
510     }
511 }
512
513
514 Value *Parser::parse_value(void) {
515     int c;
516     Value *value;
517     c = read_byte();
518     switch (c) {
519     case trace::TYPE_NULL:
520         value = new Null;
521         break;
522     case trace::TYPE_FALSE:
523         value = new Bool(false);
524         break;
525     case trace::TYPE_TRUE:
526         value = new Bool(true);
527         break;
528     case trace::TYPE_SINT:
529         value = parse_sint();
530         break;
531     case trace::TYPE_UINT:
532         value = parse_uint();
533         break;
534     case trace::TYPE_FLOAT:
535         value = parse_float();
536         break;
537     case trace::TYPE_DOUBLE:
538         value = parse_double();
539         break;
540     case trace::TYPE_STRING:
541         value = parse_string();
542         break;
543     case trace::TYPE_ENUM:
544         value = parse_enum();
545         break;
546     case trace::TYPE_BITMASK:
547         value = parse_bitmask();
548         break;
549     case trace::TYPE_ARRAY:
550         value = parse_array();
551         break;
552     case trace::TYPE_STRUCT:
553         value = parse_struct();
554         break;
555     case trace::TYPE_BLOB:
556         value = parse_blob();
557         break;
558     case trace::TYPE_OPAQUE:
559         value = parse_opaque();
560         break;
561     case trace::TYPE_REPR:
562         value = parse_repr();
563         break;
564     default:
565         std::cerr << "error: unknown type " << c << "\n";
566         exit(1);
567     case -1:
568         value = NULL;
569         break;
570     }
571 #if TRACE_VERBOSE
572     if (value) {
573         std::cerr << "\tVALUE " << value << "\n";
574     }
575 #endif
576     return value;
577 }
578
579
580 void Parser::scan_value(void) {
581     int c = read_byte();
582     switch (c) {
583     case trace::TYPE_NULL:
584     case trace::TYPE_FALSE:
585     case trace::TYPE_TRUE:
586         break;
587     case trace::TYPE_SINT:
588         scan_sint();
589         break;
590     case trace::TYPE_UINT:
591         scan_uint();
592         break;
593     case trace::TYPE_FLOAT:
594         scan_float();
595         break;
596     case trace::TYPE_DOUBLE:
597         scan_double();
598         break;
599     case trace::TYPE_STRING:
600         scan_string();
601         break;
602     case trace::TYPE_ENUM:
603         scan_enum();
604         break;
605     case trace::TYPE_BITMASK:
606         scan_bitmask();
607         break;
608     case trace::TYPE_ARRAY:
609         scan_array();
610         break;
611     case trace::TYPE_STRUCT:
612         scan_struct();
613         break;
614     case trace::TYPE_BLOB:
615         scan_blob();
616         break;
617     case trace::TYPE_OPAQUE:
618         scan_opaque();
619         break;
620     case trace::TYPE_REPR:
621         scan_repr();
622         break;
623     default:
624         std::cerr << "error: unknown type " << c << "\n";
625         exit(1);
626     case -1:
627         break;
628     }
629 }
630
631
632 Value *Parser::parse_sint() {
633     return new SInt(-(signed long long)read_uint());
634 }
635
636
637 void Parser::scan_sint() {
638     skip_uint();
639 }
640
641
642 Value *Parser::parse_uint() {
643     return new UInt(read_uint());
644 }
645
646
647 void Parser::scan_uint() {
648     skip_uint();
649 }
650
651
652 Value *Parser::parse_float() {
653     float value;
654     file->read(&value, sizeof value);
655     return new Float(value);
656 }
657
658
659 void Parser::scan_float() {
660     file->skip(sizeof(float));
661 }
662
663
664 Value *Parser::parse_double() {
665     double value;
666     file->read(&value, sizeof value);
667     return new Double(value);
668 }
669
670
671 void Parser::scan_double() {
672     file->skip(sizeof(double));
673 }
674
675
676 Value *Parser::parse_string() {
677     return new String(read_string());
678 }
679
680
681 void Parser::scan_string() {
682     skip_string();
683 }
684
685
686 Value *Parser::parse_enum() {
687     EnumSig *sig;
688     signed long long value;
689     if (version >= 3) {
690         sig = parse_enum_sig();
691         value = read_sint();
692     } else {
693         sig = parse_old_enum_sig();
694         assert(sig->num_values == 1);
695         value = sig->values->value;
696     }
697     return new Enum(sig, value);
698 }
699
700
701 void Parser::scan_enum() {
702     if (version >= 3) {
703         parse_enum_sig();
704         skip_sint();
705     } else {
706         parse_old_enum_sig();
707     }
708 }
709
710
711 Value *Parser::parse_bitmask() {
712     BitmaskSig *sig = parse_bitmask_sig();
713
714     unsigned long long value = read_uint();
715
716     return new Bitmask(sig, value);
717 }
718
719
720 void Parser::scan_bitmask() {
721     parse_bitmask_sig();
722     skip_uint(); /* value */
723 }
724
725
726 Value *Parser::parse_array(void) {
727     size_t len = read_uint();
728     Array *array = new Array(len);
729     for (size_t i = 0; i < len; ++i) {
730         array->values[i] = parse_value();
731     }
732     return array;
733 }
734
735
736 void Parser::scan_array(void) {
737     size_t len = read_uint();
738     for (size_t i = 0; i < len; ++i) {
739         scan_value();
740     }
741 }
742
743
744 Value *Parser::parse_blob(void) {
745     size_t size = read_uint();
746     Blob *blob = new Blob(size);
747     if (size) {
748         file->read(blob->buf, size);
749     }
750     return blob;
751 }
752
753
754 void Parser::scan_blob(void) {
755     size_t size = read_uint();
756     if (size) {
757         file->skip(size);
758     }
759 }
760
761
762 Value *Parser::parse_struct() {
763     StructSig *sig = parse_struct_sig();
764     Struct *value = new Struct(sig);
765
766     for (size_t i = 0; i < sig->num_members; ++i) {
767         value->members[i] = parse_value();
768     }
769
770     return value;
771 }
772
773
774 void Parser::scan_struct() {
775     StructSig *sig = parse_struct_sig();
776     for (size_t i = 0; i < sig->num_members; ++i) {
777         scan_value();
778     }
779 }
780
781
782 Value *Parser::parse_opaque() {
783     unsigned long long addr;
784     addr = read_uint();
785     return new Pointer(addr);
786 }
787
788
789 void Parser::scan_opaque() {
790     skip_uint();
791 }
792
793
794 Value *Parser::parse_repr() {
795     Value *humanValue = parse_value();
796     Value *machineValue = parse_value();
797     return new Repr(humanValue, machineValue);
798 }
799
800
801 void Parser::scan_repr() {
802     scan_value();
803     scan_value();
804 }
805
806
807 const char * Parser::read_string(void) {
808     size_t len = read_uint();
809     char * value = new char[len + 1];
810     if (len) {
811         file->read(value, len);
812     }
813     value[len] = 0;
814 #if TRACE_VERBOSE
815     std::cerr << "\tSTRING \"" << value << "\"\n";
816 #endif
817     return value;
818 }
819
820
821 void Parser::skip_string(void) {
822     size_t len = read_uint();
823     file->skip(len);
824 }
825
826
827 /*
828  * For the time being, a signed int is encoded as any other value, but we here parse
829  * it without the extra baggage of the Value class.
830  */
831 signed long long
832 Parser::read_sint(void) {
833     int c;
834     c = read_byte();
835     switch (c) {
836     case trace::TYPE_SINT:
837         return -(signed long long)read_uint();
838     case trace::TYPE_UINT:
839         return read_uint();
840     default:
841         std::cerr << "error: unexpected type " << c << "\n";
842         exit(1);
843     case -1:
844         return 0;
845     }
846 }
847
848 void
849 Parser::skip_sint(void) {
850     skip_byte();
851     skip_uint();
852 }
853
854 unsigned long long Parser::read_uint(void) {
855     unsigned long long value = 0;
856     int c;
857     unsigned shift = 0;
858     do {
859         c = file->getc();
860         if (c == -1) {
861             break;
862         }
863         value |= (unsigned long long)(c & 0x7f) << shift;
864         shift += 7;
865     } while(c & 0x80);
866 #if TRACE_VERBOSE
867     std::cerr << "\tUINT " << value << "\n";
868 #endif
869     return value;
870 }
871
872
873 void Parser::skip_uint(void) {
874     int c;
875     do {
876         c = file->getc();
877         if (c == -1) {
878             break;
879         }
880     } while(c & 0x80);
881 }
882
883
884 inline int Parser::read_byte(void) {
885     int c = file->getc();
886 #if TRACE_VERBOSE
887     if (c < 0)
888         std::cerr << "\tEOF" << "\n";
889     else
890         std::cerr << "\tBYTE 0x" << std::hex << c << std::dec << "\n";
891 #endif
892     return c;
893 }
894
895
896 inline void Parser::skip_byte(void) {
897     file->skip(1);
898 }
899
900
901 } /* namespace trace */