blob: ea6c746d9ee0f6cbe2d05be804b1301ebc73fc90 [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
52 bool parse(const char *filename) {
53 unsigned long long version;
54
55 file = gzopen(filename, "rb");
56 if (!file) {
57 return false;
58 }
59
60 version = read_uint();
61 if (version != TRACE_VERSION) {
José Fonseca501f2862010-11-19 20:41:18 +000062 std::cerr << "error: unsupported format version" << version << "\n";
José Fonseca7e329022010-11-19 17:05:18 +000063 return false;
64 }
65
66 while (!gzeof(file)) {
67 parse_call();
68 }
69
70 return true;
71 }
72
73 void parse_call(void) {
74 Call call;
75 call.name = read_string();
76 int c;
77 do {
José Fonseca5cb3e172010-11-22 16:59:34 +000078 c = read_byte();
José Fonseca7e329022010-11-19 17:05:18 +000079 if (c == Trace::CALL_END || c == -1) {
80 break;
81 }
82 switch(c) {
83 case Trace::CALL_END:
84 return;
85 case Trace::CALL_ARG:
86 call.args.push_back(parse_arg());
87 break;
88 case Trace::CALL_RET:
89 call.ret = parse_value();
90 break;
91 default:
José Fonseca501f2862010-11-19 20:41:18 +000092 std::cerr << "error: unknown call detail " << c << "\n";
José Fonseca885f2652010-11-20 11:22:25 +000093 assert(0);
José Fonseca7e329022010-11-19 17:05:18 +000094 break;
95 }
96 } while(true);
97 handle_call(call);
98 }
99
100 virtual void handle_call(Call &call) {
101 std::cout << call;
102 }
103
104 Arg parse_arg(void) {
105 std::string name = read_string();
106 Value *value = parse_value();
107 return Arg(name, value);
108 }
109
110 Value *parse_value(void) {
111 int c;
José Fonseca5cb3e172010-11-22 16:59:34 +0000112 c = read_byte();
José Fonseca7e329022010-11-19 17:05:18 +0000113 switch(c) {
José Fonsecaf6592d72010-11-21 12:44:41 +0000114 case Trace::TYPE_NULL:
115 return new Null;
José Fonsecab1887f92010-11-21 02:33:38 +0000116 case Trace::TYPE_FALSE:
117 return new Bool(false);
118 case Trace::TYPE_TRUE:
119 return new Bool(true);
José Fonseca7e329022010-11-19 17:05:18 +0000120 case Trace::TYPE_SINT:
121 return parse_sint();
122 case Trace::TYPE_UINT:
123 return parse_uint();
124 case Trace::TYPE_FLOAT:
125 return parse_float();
126 case Trace::TYPE_DOUBLE:
127 return parse_double();
128 case Trace::TYPE_STRING:
129 return parse_string();
130 case Trace::TYPE_CONST:
131 return parse_const();
132 case Trace::TYPE_BITMASK:
133 return parse_bitmask();
134 case Trace::TYPE_ARRAY:
135 return parse_array();
José Fonseca5cb3e172010-11-22 16:59:34 +0000136 case Trace::TYPE_STRUCT:
137 return parse_struct();
José Fonseca885f2652010-11-20 11:22:25 +0000138 case Trace::TYPE_BLOB:
139 return parse_blob();
José Fonseca7e329022010-11-19 17:05:18 +0000140 case Trace::TYPE_POINTER:
141 return parse_pointer();
José Fonsecaf6592d72010-11-21 12:44:41 +0000142 case Trace::TYPE_OPAQUE:
143 return parse_opaque();
José Fonseca7e329022010-11-19 17:05:18 +0000144 default:
José Fonseca501f2862010-11-19 20:41:18 +0000145 std::cerr << "error: unknown type " << c << "\n";
José Fonseca7e329022010-11-19 17:05:18 +0000146 assert(0);
147 return NULL;
148 }
149 }
150
José Fonseca7e329022010-11-19 17:05:18 +0000151 Value *parse_sint() {
152 return new SInt(-read_uint());
153 }
154
155 Value *parse_uint() {
156 return new UInt(read_uint());
157 }
158
159 Value *parse_float() {
160 float value;
161 gzread(file, &value, sizeof value);
162 return new Float(value);
163 }
164
165 Value *parse_double() {
166 double value;
167 gzread(file, &value, sizeof value);
168 return new Float(value);
169 }
170
171 Value *parse_string() {
172 return new String(read_string());
173 }
174
175 Value *parse_const() {
176 std::string name = read_string();
177 Value *value = parse_value();
178 return new Const(name, value);
179 }
180
181 Value *parse_bitmask() {
182 unsigned long long value = 0;
183 int c;
184 do {
José Fonseca5cb3e172010-11-22 16:59:34 +0000185 c = read_byte();
José Fonseca7e329022010-11-19 17:05:18 +0000186 switch(c) {
187 case Trace::TYPE_SINT:
188 value |= -read_uint();
189 break;
190 case Trace::TYPE_UINT:
191 value |= read_uint();
192 break;
193 case Trace::TYPE_CONST:
194 read_string();
195 break;
José Fonsecab1887f92010-11-21 02:33:38 +0000196 case Trace::TYPE_NULL:
José Fonseca7e329022010-11-19 17:05:18 +0000197 goto done;
198 default:
José Fonseca501f2862010-11-19 20:41:18 +0000199 std::cerr << "error: uexpected type " << c << "\n";
José Fonseca7e329022010-11-19 17:05:18 +0000200 assert(0);
201 return NULL;
202 }
203 } while(true);
204done:
205 return new UInt(value);
206 }
207
José Fonseca885f2652010-11-20 11:22:25 +0000208 Value *parse_array(void) {
José Fonseca7e329022010-11-19 17:05:18 +0000209 size_t len = read_uint();
210 Array *array = new Array(len);
211 for (size_t i = 0; i < len; ++i) {
212 array->values[i] = parse_value();
213 }
214 return array;
215 }
216
José Fonseca885f2652010-11-20 11:22:25 +0000217 Value *parse_blob(void) {
218 size_t size = read_uint();
219 Blob *blob = new Blob(size);
220 if (size) {
221 gzread(file, blob->buf, size);
222 }
223 return blob;
224 }
225
José Fonseca7e329022010-11-19 17:05:18 +0000226 Value *parse_pointer() {
227 unsigned long long addr;
228 Value *value;
229 addr = read_uint();
230 value = parse_value();
231 if (!value)
232 value = new UInt(addr);
233 return value;
234 }
235
José Fonseca5cb3e172010-11-22 16:59:34 +0000236 Value *parse_struct() {
237 std::string name;
238 /* XXX */
239 name = read_string();
240 while(name.length()) {
241 Value *value = parse_value();
242 std::cout << " " << name << " = " << value << "\n";
243 name = read_string();
244 }
245 return NULL;
246 }
247
José Fonsecaf6592d72010-11-21 12:44:41 +0000248 Value *parse_opaque() {
249 unsigned long long addr;
250 addr = read_uint();
251 /* XXX */
252 return new UInt(addr);
253 }
254
José Fonseca7e329022010-11-19 17:05:18 +0000255 std::string read_string(void) {
256 size_t len = read_uint();
José Fonseca5cb3e172010-11-22 16:59:34 +0000257 if (!len) {
258 return std::string();
259 }
José Fonseca7e329022010-11-19 17:05:18 +0000260 char * buf = new char[len];
261 gzread(file, buf, len);
262 std::string value(buf, len);
263 delete [] buf;
José Fonseca5cb3e172010-11-22 16:59:34 +0000264#ifdef TRACE_VERBOSE
265 std::cerr << '"' << value << '"' << "\n";
266#endif
José Fonseca7e329022010-11-19 17:05:18 +0000267 return value;
268 }
269
270 unsigned long long read_uint(void) {
271 unsigned long long value = 0;
272 int c;
273 unsigned shift = 0;
274 do {
275 c = gzgetc(file);
276 if (c == -1) {
277 break;
278 }
279 value |= (unsigned long long)(c & 0x7f) << shift;
280 shift += 7;
281 } while(c & 0x80);
José Fonseca5cb3e172010-11-22 16:59:34 +0000282#ifdef TRACE_VERBOSE
283 std::cerr << value << "\n";
284#endif
José Fonseca7e329022010-11-19 17:05:18 +0000285 return value;
286 }
José Fonseca5cb3e172010-11-22 16:59:34 +0000287
288 int read_byte(void) {
289 int c = gzgetc(file);
290#ifdef TRACE_VERBOSE
291 if (c < 0)
292 std::cerr << "EOF" << "\n";
293 else
294 std::cerr << "0x" << std::hex << c << "\n";
295#endif
296 return c;
297 }
José Fonseca7e329022010-11-19 17:05:18 +0000298};
299
300
301} /* namespace Trace */
302
303#endif /* _TRACE_PARSER_HPP_ */