blob: 97dcf657b71f30ad132bbd21bb3cd6f448bb9a72 [file] [log] [blame]
José Fonseca7e329022010-11-19 17:05:18 +00001/**************************************************************************
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
34#include <zlib.h>
35
36#include "trace_format.hpp"
37#include "trace_model.hpp"
38
39
40namespace Trace {
41
42
43class Parser
44{
45protected:
46 gzFile file;
47public:
48 Parser() {
49 file = NULL;
50 }
51
José Fonseca6f51d3b2010-11-22 19:56:19 +000052 ~Parser() {
53 close();
54 }
55
56 bool open(const char *filename) {
José Fonseca7e329022010-11-19 17:05:18 +000057 unsigned long long version;
58
59 file = gzopen(filename, "rb");
60 if (!file) {
61 return false;
62 }
63
64 version = read_uint();
65 if (version != TRACE_VERSION) {
José Fonseca501f2862010-11-19 20:41:18 +000066 std::cerr << "error: unsupported format version" << version << "\n";
José Fonseca7e329022010-11-19 17:05:18 +000067 return false;
68 }
69
José Fonseca7e329022010-11-19 17:05:18 +000070 return true;
71 }
72
José Fonseca6f51d3b2010-11-22 19:56:19 +000073 void close(void) {
74 if (file) {
75 gzclose(file);
76 file = NULL;
77 }
78 }
79
80 Call *parse_call(void) {
81 Call *call = new Call;
82 call->name = read_string();
José Fonseca7e329022010-11-19 17:05:18 +000083 do {
José Fonseca6f51d3b2010-11-22 19:56:19 +000084 int c = read_byte();
José Fonseca7e329022010-11-19 17:05:18 +000085 switch(c) {
86 case Trace::CALL_END:
José Fonseca6f51d3b2010-11-22 19:56:19 +000087 return call;
José Fonseca7e329022010-11-19 17:05:18 +000088 case Trace::CALL_ARG:
José Fonsecadce84c42010-11-24 16:19:49 +000089 parse_arg(call);
José Fonseca7e329022010-11-19 17:05:18 +000090 break;
91 case Trace::CALL_RET:
José Fonseca6f51d3b2010-11-22 19:56:19 +000092 call->ret = parse_value();
José Fonseca7e329022010-11-19 17:05:18 +000093 break;
94 default:
José Fonseca501f2862010-11-19 20:41:18 +000095 std::cerr << "error: unknown call detail " << c << "\n";
José Fonseca885f2652010-11-20 11:22:25 +000096 assert(0);
José Fonseca6f51d3b2010-11-22 19:56:19 +000097 /* fallthrough */
98 case -1:
99 delete call;
100 return NULL;
José Fonseca7e329022010-11-19 17:05:18 +0000101 }
102 } while(true);
José Fonseca7e329022010-11-19 17:05:18 +0000103 }
104
José Fonsecadce84c42010-11-24 16:19:49 +0000105 void parse_arg(Call *call) {
106 unsigned index = read_uint();
José Fonseca7e329022010-11-19 17:05:18 +0000107 std::string name = read_string();
108 Value *value = parse_value();
José Fonsecadce84c42010-11-24 16:19:49 +0000109 if (index >= call->args.size()) {
110 call->args.resize(index + 1);
111 }
112 call->args[index] = Arg(name, value);
José Fonseca7e329022010-11-19 17:05:18 +0000113 }
114
115 Value *parse_value(void) {
116 int c;
José Fonseca5cb3e172010-11-22 16:59:34 +0000117 c = read_byte();
José Fonseca7e329022010-11-19 17:05:18 +0000118 switch(c) {
José Fonsecaf6592d72010-11-21 12:44:41 +0000119 case Trace::TYPE_NULL:
120 return new Null;
José Fonsecab1887f92010-11-21 02:33:38 +0000121 case Trace::TYPE_FALSE:
122 return new Bool(false);
123 case Trace::TYPE_TRUE:
124 return new Bool(true);
José Fonseca7e329022010-11-19 17:05:18 +0000125 case Trace::TYPE_SINT:
126 return parse_sint();
127 case Trace::TYPE_UINT:
128 return parse_uint();
129 case Trace::TYPE_FLOAT:
130 return parse_float();
131 case Trace::TYPE_DOUBLE:
132 return parse_double();
133 case Trace::TYPE_STRING:
134 return parse_string();
135 case Trace::TYPE_CONST:
136 return parse_const();
137 case Trace::TYPE_BITMASK:
138 return parse_bitmask();
139 case Trace::TYPE_ARRAY:
140 return parse_array();
José Fonseca5cb3e172010-11-22 16:59:34 +0000141 case Trace::TYPE_STRUCT:
142 return parse_struct();
José Fonseca885f2652010-11-20 11:22:25 +0000143 case Trace::TYPE_BLOB:
144 return parse_blob();
José Fonsecaf6592d72010-11-21 12:44:41 +0000145 case Trace::TYPE_OPAQUE:
146 return parse_opaque();
José Fonseca7e329022010-11-19 17:05:18 +0000147 default:
José Fonseca501f2862010-11-19 20:41:18 +0000148 std::cerr << "error: unknown type " << c << "\n";
José Fonseca7e329022010-11-19 17:05:18 +0000149 assert(0);
150 return NULL;
151 }
152 }
153
José Fonseca7e329022010-11-19 17:05:18 +0000154 Value *parse_sint() {
155 return new SInt(-read_uint());
156 }
157
158 Value *parse_uint() {
159 return new UInt(read_uint());
160 }
161
162 Value *parse_float() {
163 float value;
164 gzread(file, &value, sizeof value);
165 return new Float(value);
166 }
167
168 Value *parse_double() {
169 double value;
170 gzread(file, &value, sizeof value);
171 return new Float(value);
172 }
173
174 Value *parse_string() {
175 return new String(read_string());
176 }
177
178 Value *parse_const() {
179 std::string name = read_string();
180 Value *value = parse_value();
181 return new Const(name, value);
182 }
183
184 Value *parse_bitmask() {
185 unsigned long long value = 0;
186 int c;
187 do {
José Fonseca5cb3e172010-11-22 16:59:34 +0000188 c = read_byte();
José Fonseca7e329022010-11-19 17:05:18 +0000189 switch(c) {
190 case Trace::TYPE_SINT:
191 value |= -read_uint();
192 break;
193 case Trace::TYPE_UINT:
194 value |= read_uint();
195 break;
196 case Trace::TYPE_CONST:
197 read_string();
198 break;
José Fonsecab1887f92010-11-21 02:33:38 +0000199 case Trace::TYPE_NULL:
José Fonseca7e329022010-11-19 17:05:18 +0000200 goto done;
201 default:
José Fonseca501f2862010-11-19 20:41:18 +0000202 std::cerr << "error: uexpected type " << c << "\n";
José Fonseca7e329022010-11-19 17:05:18 +0000203 assert(0);
204 return NULL;
205 }
206 } while(true);
207done:
208 return new UInt(value);
209 }
210
José Fonseca885f2652010-11-20 11:22:25 +0000211 Value *parse_array(void) {
José Fonseca7e329022010-11-19 17:05:18 +0000212 size_t len = read_uint();
213 Array *array = new Array(len);
214 for (size_t i = 0; i < len; ++i) {
215 array->values[i] = parse_value();
216 }
217 return array;
218 }
219
José Fonseca885f2652010-11-20 11:22:25 +0000220 Value *parse_blob(void) {
221 size_t size = read_uint();
222 Blob *blob = new Blob(size);
223 if (size) {
224 gzread(file, blob->buf, size);
225 }
226 return blob;
227 }
228
José Fonseca5cb3e172010-11-22 16:59:34 +0000229 Value *parse_struct() {
230 std::string name;
231 /* XXX */
232 name = read_string();
233 while(name.length()) {
234 Value *value = parse_value();
235 std::cout << " " << name << " = " << value << "\n";
236 name = read_string();
237 }
238 return NULL;
239 }
240
José Fonsecaf6592d72010-11-21 12:44:41 +0000241 Value *parse_opaque() {
242 unsigned long long addr;
243 addr = read_uint();
244 /* XXX */
245 return new UInt(addr);
246 }
247
José Fonseca7e329022010-11-19 17:05:18 +0000248 std::string read_string(void) {
249 size_t len = read_uint();
José Fonseca5cb3e172010-11-22 16:59:34 +0000250 if (!len) {
251 return std::string();
252 }
José Fonseca7e329022010-11-19 17:05:18 +0000253 char * buf = new char[len];
254 gzread(file, buf, len);
255 std::string value(buf, len);
256 delete [] buf;
José Fonseca5cb3e172010-11-22 16:59:34 +0000257#ifdef TRACE_VERBOSE
258 std::cerr << '"' << value << '"' << "\n";
259#endif
José Fonseca7e329022010-11-19 17:05:18 +0000260 return value;
261 }
262
263 unsigned long long read_uint(void) {
264 unsigned long long value = 0;
265 int c;
266 unsigned shift = 0;
267 do {
268 c = gzgetc(file);
269 if (c == -1) {
270 break;
271 }
272 value |= (unsigned long long)(c & 0x7f) << shift;
273 shift += 7;
274 } while(c & 0x80);
José Fonseca5cb3e172010-11-22 16:59:34 +0000275#ifdef TRACE_VERBOSE
276 std::cerr << value << "\n";
277#endif
José Fonseca7e329022010-11-19 17:05:18 +0000278 return value;
279 }
José Fonseca5cb3e172010-11-22 16:59:34 +0000280
281 int read_byte(void) {
282 int c = gzgetc(file);
283#ifdef TRACE_VERBOSE
284 if (c < 0)
285 std::cerr << "EOF" << "\n";
286 else
287 std::cerr << "0x" << std::hex << c << "\n";
288#endif
289 return c;
290 }
José Fonseca7e329022010-11-19 17:05:18 +0000291};
292
293
294} /* namespace Trace */
295
296#endif /* _TRACE_PARSER_HPP_ */