]> git.cworth.org Git - apitrace/blob - trace_parser.hpp
Trace parse debugging.
[apitrace] / trace_parser.hpp
1 /**************************************************************************
2  *
3  * Copyright 2010 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 #ifndef _TRACE_PARSER_HPP_
27 #define _TRACE_PARSER_HPP_
28
29
30 #include <cassert>
31
32 #include <iostream>
33 #include <map>
34 #include <string>
35
36 #include <zlib.h>
37
38 #include "trace_format.hpp"
39 #include "trace_model.hpp"
40
41
42 #define TRACE_VERBOSE 0
43
44
45 namespace Trace {
46
47
48 class Parser
49 {
50 protected:
51    gzFile file;
52
53    typedef std::map<size_t, std::string> namemap;
54    namemap names;
55
56 public:
57    Parser() {
58       file = NULL;
59    }
60
61    ~Parser() {
62       close();
63    }
64
65    bool open(const char *filename) {
66       unsigned long long version;
67
68       file = gzopen(filename, "rb");
69       if (!file) {
70          return false;
71       }
72
73       version = read_uint();
74       if (version != TRACE_VERSION) {
75          std::cerr << "error: unsupported format version" << version << "\n";
76          return false;
77       }
78
79       return true;
80    }
81
82    void close(void) {
83       if (file) {
84          gzclose(file);
85          file = NULL;
86       }
87    }
88
89    Call *parse_call(void) {
90       Call *call = new Call;
91       call->name = read_name();
92       do {
93          int c = read_byte();
94          switch(c) {
95          case Trace::CALL_END:
96             return call;
97          case Trace::CALL_ARG:
98             parse_arg(call);
99             break;
100          case Trace::CALL_RET:
101             call->ret = parse_value();
102             break;
103          default:
104             std::cerr << "error: unknown call detail " << c << "\n";
105             assert(0);
106             /* fallthrough */
107          case -1:
108             delete call;
109             return NULL;
110          }
111       } while(true);
112    }
113    
114    void parse_arg(Call *call) {
115       unsigned index = read_uint();
116       std::string name = read_name();
117       Value *value = parse_value();
118       if (index >= call->args.size()) {
119           call->args.resize(index + 1);
120       }
121       call->args[index] = Arg(name, value);
122    }
123    
124    Value *parse_value(void) {
125       int c;
126       c = read_byte();
127       switch(c) {
128       case Trace::TYPE_NULL:
129          return new Null;
130       case Trace::TYPE_FALSE:
131          return new Bool(false);
132       case Trace::TYPE_TRUE:
133          return new Bool(true);
134       case Trace::TYPE_SINT:
135          return parse_sint();
136       case Trace::TYPE_UINT:
137          return parse_uint();
138       case Trace::TYPE_FLOAT:
139          return parse_float();
140       case Trace::TYPE_DOUBLE:
141          return parse_double();
142       case Trace::TYPE_STRING:
143          return parse_string();
144       case Trace::TYPE_CONST:
145          return parse_const();
146       case Trace::TYPE_BITMASK:
147          return parse_bitmask();
148       case Trace::TYPE_ARRAY:
149          return parse_array();
150       case Trace::TYPE_STRUCT:
151          return parse_struct();
152       case Trace::TYPE_BLOB:
153          return parse_blob();
154       case Trace::TYPE_OPAQUE:
155          return parse_opaque();
156       default:
157          std::cerr << "error: unknown type " << c << "\n";
158          assert(0);
159          return NULL;
160       }
161    }
162
163    Value *parse_sint() {
164       return new SInt(-(signed long long)read_uint());
165    }
166    
167    Value *parse_uint() {
168       return new UInt(read_uint());
169    }
170    
171    Value *parse_float() {
172       float value;
173       gzread(file, &value, sizeof value);
174       return new Float(value);
175    }
176    
177    Value *parse_double() {
178       double value;
179       gzread(file, &value, sizeof value);
180       return new Float(value);
181    }
182    
183    Value *parse_string() {
184       return new String(read_string());
185    }
186    
187    Value *parse_const() {
188       std::string name = read_name();
189       Value *value = parse_value();
190       return new Const(name, value);
191    }
192    
193    Value *parse_bitmask() {
194       unsigned long long value = 0;
195       int c;
196       do {
197          c = read_byte();
198          switch(c) {
199          case Trace::TYPE_SINT:
200             value |= -(signed long long)read_uint();
201             break;
202          case Trace::TYPE_UINT:
203             value |= read_uint();
204             break;
205          case Trace::TYPE_CONST:
206             read_name();
207             break;
208          case Trace::TYPE_NULL:
209             goto done;
210          default:
211             std::cerr << "error: uexpected type " << c << "\n";
212             assert(0);
213             return NULL;
214          }
215       } while(true);
216 done:
217       return new UInt(value);
218    }
219
220    Value *parse_array(void) {
221       size_t len = read_uint();
222       Array *array = new Array(len);
223       for (size_t i = 0; i < len; ++i) {
224          array->values[i] = parse_value();
225       }
226       return array;
227    }
228    
229    Value *parse_blob(void) {
230       size_t size = read_uint();
231       Blob *blob = new Blob(size);
232       if (size) {
233           gzread(file, blob->buf, size);
234       }
235       return blob;
236    }
237    
238    Value *parse_struct() {
239       size_t length = read_uint();
240       /* XXX */
241       for (size_t i = 0; i < length; ++i) {
242          std::string name = read_name();
243          Value *value = parse_value();
244          std::cout << "  " << name << " = " << value << "\n";
245       }
246       return NULL;
247    }
248    
249    Value *parse_opaque() {
250       unsigned long long addr;
251       addr = read_uint();
252       /* XXX */
253       return new UInt(addr);
254    }
255
256    std::string read_name(void) {
257        std::string name;
258        size_t id = read_uint();
259        if (id >= names.size()) {
260            assert(id == names.size());
261            name = read_string();
262            names[id] = name;
263            return name;
264        } else {
265            name = names[id];
266        }
267 #if TRACE_VERBOSE
268        std::cerr << "\tNAME " << id << " " << name << "\n";
269 #endif
270        return name;
271    }
272    
273    std::string read_string(void) {
274       size_t len = read_uint();
275       if (!len) {
276          return std::string();
277       }
278       char * buf = new char[len];
279       gzread(file, buf, len);
280       std::string value(buf, len);
281       delete [] buf;
282 #if TRACE_VERBOSE
283       std::cerr << "\tSTRING \"" << value << "\"\n";
284 #endif
285       return value;
286    }
287
288    unsigned long long read_uint(void) {
289       unsigned long long value = 0;
290       int c;
291       unsigned shift = 0;
292       do {
293          c = gzgetc(file);
294          if (c == -1) {
295             break;
296          }
297          value |= (unsigned long long)(c & 0x7f) << shift;
298          shift += 7;
299       } while(c & 0x80);
300 #if TRACE_VERBOSE
301       std::cerr << "\tUINT " << value << "\n";
302 #endif
303       return value;
304    }
305
306    int read_byte(void) {
307       int c = gzgetc(file);
308 #if TRACE_VERBOSE
309       if (c < 0)
310          std::cerr << "\tEOF" << "\n";
311       else
312          std::cerr << "\tBYTE 0x" << std::hex << c << std::dec << "\n";
313 #endif
314       return c;
315    }
316 };
317
318
319 } /* namespace Trace */
320
321 #endif /* _TRACE_PARSER_HPP_ */