blob: 6a2c92f352ddedfba4b021220d36ef6f9230f76e [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>
José Fonsecafa922142010-11-25 09:36:04 +000033#include <map>
34#include <string>
José Fonseca7e329022010-11-19 17:05:18 +000035
36#include <zlib.h>
37
38#include "trace_format.hpp"
39#include "trace_model.hpp"
40
41
José Fonsecaf4b071e2010-11-25 15:48:46 +000042#define TRACE_VERBOSE 0
43
44
José Fonseca7e329022010-11-19 17:05:18 +000045namespace Trace {
46
47
48class Parser
49{
50protected:
51 gzFile file;
José Fonsecafa922142010-11-25 09:36:04 +000052
53 typedef std::map<size_t, std::string> namemap;
54 namemap names;
55
José Fonseca7e329022010-11-19 17:05:18 +000056public:
57 Parser() {
58 file = NULL;
59 }
60
José Fonseca6f51d3b2010-11-22 19:56:19 +000061 ~Parser() {
62 close();
63 }
64
65 bool open(const char *filename) {
José Fonseca7e329022010-11-19 17:05:18 +000066 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) {
José Fonseca501f2862010-11-19 20:41:18 +000075 std::cerr << "error: unsupported format version" << version << "\n";
José Fonseca7e329022010-11-19 17:05:18 +000076 return false;
77 }
78
José Fonseca7e329022010-11-19 17:05:18 +000079 return true;
80 }
81
José Fonseca6f51d3b2010-11-22 19:56:19 +000082 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;
José Fonsecafa922142010-11-25 09:36:04 +000091 call->name = read_name();
José Fonseca7e329022010-11-19 17:05:18 +000092 do {
José Fonseca6f51d3b2010-11-22 19:56:19 +000093 int c = read_byte();
José Fonseca7e329022010-11-19 17:05:18 +000094 switch(c) {
95 case Trace::CALL_END:
José Fonseca6f51d3b2010-11-22 19:56:19 +000096 return call;
José Fonseca7e329022010-11-19 17:05:18 +000097 case Trace::CALL_ARG:
José Fonsecadce84c42010-11-24 16:19:49 +000098 parse_arg(call);
José Fonseca7e329022010-11-19 17:05:18 +000099 break;
100 case Trace::CALL_RET:
José Fonseca6f51d3b2010-11-22 19:56:19 +0000101 call->ret = parse_value();
José Fonseca7e329022010-11-19 17:05:18 +0000102 break;
103 default:
José Fonseca501f2862010-11-19 20:41:18 +0000104 std::cerr << "error: unknown call detail " << c << "\n";
José Fonseca885f2652010-11-20 11:22:25 +0000105 assert(0);
José Fonseca6f51d3b2010-11-22 19:56:19 +0000106 /* fallthrough */
107 case -1:
108 delete call;
109 return NULL;
José Fonseca7e329022010-11-19 17:05:18 +0000110 }
111 } while(true);
José Fonseca7e329022010-11-19 17:05:18 +0000112 }
113
José Fonsecadce84c42010-11-24 16:19:49 +0000114 void parse_arg(Call *call) {
115 unsigned index = read_uint();
José Fonsecafa922142010-11-25 09:36:04 +0000116 std::string name = read_name();
José Fonseca7e329022010-11-19 17:05:18 +0000117 Value *value = parse_value();
José Fonsecadce84c42010-11-24 16:19:49 +0000118 if (index >= call->args.size()) {
119 call->args.resize(index + 1);
120 }
121 call->args[index] = Arg(name, value);
José Fonseca7e329022010-11-19 17:05:18 +0000122 }
123
124 Value *parse_value(void) {
125 int c;
José Fonseca5cb3e172010-11-22 16:59:34 +0000126 c = read_byte();
José Fonseca7e329022010-11-19 17:05:18 +0000127 switch(c) {
José Fonsecaf6592d72010-11-21 12:44:41 +0000128 case Trace::TYPE_NULL:
129 return new Null;
José Fonsecab1887f92010-11-21 02:33:38 +0000130 case Trace::TYPE_FALSE:
131 return new Bool(false);
132 case Trace::TYPE_TRUE:
133 return new Bool(true);
José Fonseca7e329022010-11-19 17:05:18 +0000134 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();
José Fonseca5cb3e172010-11-22 16:59:34 +0000150 case Trace::TYPE_STRUCT:
151 return parse_struct();
José Fonseca885f2652010-11-20 11:22:25 +0000152 case Trace::TYPE_BLOB:
153 return parse_blob();
José Fonsecaf6592d72010-11-21 12:44:41 +0000154 case Trace::TYPE_OPAQUE:
155 return parse_opaque();
José Fonseca7e329022010-11-19 17:05:18 +0000156 default:
José Fonseca501f2862010-11-19 20:41:18 +0000157 std::cerr << "error: unknown type " << c << "\n";
José Fonseca7e329022010-11-19 17:05:18 +0000158 assert(0);
159 return NULL;
160 }
161 }
162
José Fonseca7e329022010-11-19 17:05:18 +0000163 Value *parse_sint() {
José Fonseca0633bdf2010-11-25 14:54:14 +0000164 return new SInt(-(signed long long)read_uint());
José Fonseca7e329022010-11-19 17:05:18 +0000165 }
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() {
José Fonsecafa922142010-11-25 09:36:04 +0000188 std::string name = read_name();
José Fonseca7e329022010-11-19 17:05:18 +0000189 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 {
José Fonseca5cb3e172010-11-22 16:59:34 +0000197 c = read_byte();
José Fonseca7e329022010-11-19 17:05:18 +0000198 switch(c) {
199 case Trace::TYPE_SINT:
José Fonseca0633bdf2010-11-25 14:54:14 +0000200 value |= -(signed long long)read_uint();
José Fonseca7e329022010-11-19 17:05:18 +0000201 break;
202 case Trace::TYPE_UINT:
203 value |= read_uint();
204 break;
205 case Trace::TYPE_CONST:
José Fonsecafa922142010-11-25 09:36:04 +0000206 read_name();
José Fonseca7e329022010-11-19 17:05:18 +0000207 break;
José Fonsecab1887f92010-11-21 02:33:38 +0000208 case Trace::TYPE_NULL:
José Fonseca7e329022010-11-19 17:05:18 +0000209 goto done;
210 default:
José Fonseca501f2862010-11-19 20:41:18 +0000211 std::cerr << "error: uexpected type " << c << "\n";
José Fonseca7e329022010-11-19 17:05:18 +0000212 assert(0);
213 return NULL;
214 }
215 } while(true);
216done:
217 return new UInt(value);
218 }
219
José Fonseca885f2652010-11-20 11:22:25 +0000220 Value *parse_array(void) {
José Fonseca7e329022010-11-19 17:05:18 +0000221 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
José Fonseca885f2652010-11-20 11:22:25 +0000229 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
José Fonseca5cb3e172010-11-22 16:59:34 +0000238 Value *parse_struct() {
José Fonsecafa922142010-11-25 09:36:04 +0000239 size_t length = read_uint();
José Fonseca5cb3e172010-11-22 16:59:34 +0000240 /* XXX */
José Fonseca0633bdf2010-11-25 14:54:14 +0000241 for (size_t i = 0; i < length; ++i) {
José Fonsecafa922142010-11-25 09:36:04 +0000242 std::string name = read_name();
José Fonseca5cb3e172010-11-22 16:59:34 +0000243 Value *value = parse_value();
244 std::cout << " " << name << " = " << value << "\n";
José Fonseca5cb3e172010-11-22 16:59:34 +0000245 }
246 return NULL;
247 }
248
José Fonsecaf6592d72010-11-21 12:44:41 +0000249 Value *parse_opaque() {
250 unsigned long long addr;
251 addr = read_uint();
252 /* XXX */
253 return new UInt(addr);
254 }
José Fonsecafa922142010-11-25 09:36:04 +0000255
256 std::string read_name(void) {
257 std::string name;
258 size_t id = read_uint();
259 if (id >= names.size()) {
José Fonsecaf4b071e2010-11-25 15:48:46 +0000260 assert(id == names.size());
José Fonsecafa922142010-11-25 09:36:04 +0000261 name = read_string();
262 names[id] = name;
263 return name;
264 } else {
José Fonsecaf4b071e2010-11-25 15:48:46 +0000265 name = names[id];
José Fonsecafa922142010-11-25 09:36:04 +0000266 }
José Fonsecaf4b071e2010-11-25 15:48:46 +0000267#if TRACE_VERBOSE
268 std::cerr << "\tNAME " << id << " " << name << "\n";
269#endif
270 return name;
José Fonsecafa922142010-11-25 09:36:04 +0000271 }
José Fonsecaf6592d72010-11-21 12:44:41 +0000272
José Fonseca7e329022010-11-19 17:05:18 +0000273 std::string read_string(void) {
274 size_t len = read_uint();
José Fonseca5cb3e172010-11-22 16:59:34 +0000275 if (!len) {
276 return std::string();
277 }
José Fonseca7e329022010-11-19 17:05:18 +0000278 char * buf = new char[len];
279 gzread(file, buf, len);
280 std::string value(buf, len);
281 delete [] buf;
José Fonsecaf4b071e2010-11-25 15:48:46 +0000282#if TRACE_VERBOSE
283 std::cerr << "\tSTRING \"" << value << "\"\n";
José Fonseca5cb3e172010-11-22 16:59:34 +0000284#endif
José Fonseca7e329022010-11-19 17:05:18 +0000285 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);
José Fonsecaf4b071e2010-11-25 15:48:46 +0000300#if TRACE_VERBOSE
301 std::cerr << "\tUINT " << value << "\n";
José Fonseca5cb3e172010-11-22 16:59:34 +0000302#endif
José Fonseca7e329022010-11-19 17:05:18 +0000303 return value;
304 }
José Fonseca5cb3e172010-11-22 16:59:34 +0000305
306 int read_byte(void) {
307 int c = gzgetc(file);
José Fonsecaf4b071e2010-11-25 15:48:46 +0000308#if TRACE_VERBOSE
José Fonseca5cb3e172010-11-22 16:59:34 +0000309 if (c < 0)
José Fonsecaf4b071e2010-11-25 15:48:46 +0000310 std::cerr << "\tEOF" << "\n";
José Fonseca5cb3e172010-11-22 16:59:34 +0000311 else
José Fonsecaf4b071e2010-11-25 15:48:46 +0000312 std::cerr << "\tBYTE 0x" << std::hex << c << std::dec << "\n";
José Fonseca5cb3e172010-11-22 16:59:34 +0000313#endif
314 return c;
315 }
José Fonseca7e329022010-11-19 17:05:18 +0000316};
317
318
319} /* namespace Trace */
320
321#endif /* _TRACE_PARSER_HPP_ */