]> git.cworth.org Git - apitrace/blob - common/trace_writer.cpp
image: Add floating point support.
[apitrace] / common / trace_writer.cpp
1 /**************************************************************************
2  *
3  * Copyright 2007-2009 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
27 #include <assert.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <vector>
33
34 #include "os.hpp"
35 #include "trace_file.hpp"
36 #include "trace_writer.hpp"
37 #include "trace_format.hpp"
38 #include "trace_backtrace.hpp"
39
40 namespace trace {
41
42
43 Writer::Writer() :
44     call_no(0)
45 {
46     m_file = File::createSnappy();
47     close();
48 }
49
50 Writer::~Writer()
51 {
52     close();
53     delete m_file;
54     m_file = NULL;
55 }
56
57 void
58 Writer::close(void) {
59     m_file->close();
60 }
61
62 bool
63 Writer::open(const char *filename) {
64     close();
65
66     if (!m_file->open(filename, File::Write)) {
67         return false;
68     }
69
70     call_no = 0;
71     functions.clear();
72     structs.clear();
73     enums.clear();
74     bitmasks.clear();
75     frames.clear();
76
77     _writeUInt(TRACE_VERSION);
78
79     return true;
80 }
81
82 void inline
83 Writer::_write(const void *sBuffer, size_t dwBytesToWrite) {
84     m_file->write(sBuffer, dwBytesToWrite);
85 }
86
87 void inline
88 Writer::_writeByte(char c) {
89     _write(&c, 1);
90 }
91
92 void inline
93 Writer::_writeUInt(unsigned long long value) {
94     char buf[2 * sizeof value];
95     unsigned len;
96
97     len = 0;
98     do {
99         assert(len < sizeof buf);
100         buf[len] = 0x80 | (value & 0x7f);
101         value >>= 7;
102         ++len;
103     } while (value);
104
105     assert(len);
106     buf[len - 1] &= 0x7f;
107
108     _write(buf, len);
109 }
110
111 void inline
112 Writer::_writeFloat(float value) {
113     assert(sizeof value == 4);
114     _write((const char *)&value, sizeof value);
115 }
116
117 void inline
118 Writer::_writeDouble(double value) {
119     assert(sizeof value == 8);
120     _write((const char *)&value, sizeof value);
121 }
122
123 void inline
124 Writer::_writeString(const char *str) {
125     size_t len = strlen(str);
126     _writeUInt(len);
127     _write(str, len);
128 }
129
130 inline bool lookup(std::vector<bool> &map, size_t index) {
131     if (index >= map.size()) {
132         map.resize(index + 1);
133         return false;
134     } else {
135         return map[index];
136     }
137 }
138
139 void Writer::beginBacktrace(unsigned num_frames) {
140     if (num_frames) {
141         _writeByte(trace::CALL_BACKTRACE);
142         _writeUInt(num_frames);
143     }
144 }
145
146 void Writer::writeStackFrame(const RawStackFrame *frame) {
147     _writeUInt(frame->id);
148     if (!lookup(frames, frame->id)) {
149         if (frame->module != NULL) {
150             _writeByte(trace::BACKTRACE_MODULE);
151             _writeString(frame->module);
152         }
153         if (frame->function != NULL) {
154             _writeByte(trace::BACKTRACE_FUNCTION);
155             _writeString(frame->function);
156         }
157         if (frame->filename != NULL) {
158             _writeByte(trace::BACKTRACE_FILENAME);
159             _writeString(frame->filename);
160         }
161         if (frame->linenumber >= 0) {
162             _writeByte(trace::BACKTRACE_LINENUMBER);
163             _writeUInt(frame->linenumber);
164         }
165         if (frame->offset >= 0) {
166             _writeByte(trace::BACKTRACE_OFFSET);
167             _writeUInt(frame->offset);
168         }
169         _writeByte(trace::BACKTRACE_END);
170         frames[frame->id] = true;
171     }
172 }
173
174 unsigned Writer::beginEnter(const FunctionSig *sig, unsigned thread_id) {
175     _writeByte(trace::EVENT_ENTER);
176     _writeUInt(thread_id);
177     _writeUInt(sig->id);
178     if (!lookup(functions, sig->id)) {
179         _writeString(sig->name);
180         _writeUInt(sig->num_args);
181         for (unsigned i = 0; i < sig->num_args; ++i) {
182             _writeString(sig->arg_names[i]);
183         }
184         functions[sig->id] = true;
185     }
186
187     return call_no++;
188 }
189
190 void Writer::endEnter(void) {
191     _writeByte(trace::CALL_END);
192 }
193
194 void Writer::beginLeave(unsigned call) {
195     _writeByte(trace::EVENT_LEAVE);
196     _writeUInt(call);
197 }
198
199 void Writer::endLeave(void) {
200     _writeByte(trace::CALL_END);
201 }
202
203 void Writer::beginArg(unsigned index) {
204     _writeByte(trace::CALL_ARG);
205     _writeUInt(index);
206 }
207
208 void Writer::beginReturn(void) {
209     _writeByte(trace::CALL_RET);
210 }
211
212 void Writer::beginArray(size_t length) {
213     _writeByte(trace::TYPE_ARRAY);
214     _writeUInt(length);
215 }
216
217 void Writer::beginStruct(const StructSig *sig) {
218     _writeByte(trace::TYPE_STRUCT);
219     _writeUInt(sig->id);
220     if (!lookup(structs, sig->id)) {
221         _writeString(sig->name);
222         _writeUInt(sig->num_members);
223         for (unsigned i = 0; i < sig->num_members; ++i) {
224             _writeString(sig->member_names[i]);
225         }
226         structs[sig->id] = true;
227     }
228 }
229
230 void Writer::beginRepr(void) {
231     _writeByte(trace::TYPE_REPR);
232 }
233
234 void Writer::writeBool(bool value) {
235     _writeByte(value ? trace::TYPE_TRUE : trace::TYPE_FALSE);
236 }
237
238 void Writer::writeSInt(signed long long value) {
239     if (value < 0) {
240         _writeByte(trace::TYPE_SINT);
241         _writeUInt(-value);
242     } else {
243         _writeByte(trace::TYPE_UINT);
244         _writeUInt(value);
245     }
246 }
247
248 void Writer::writeUInt(unsigned long long value) {
249     _writeByte(trace::TYPE_UINT);
250     _writeUInt(value);
251 }
252
253 void Writer::writeFloat(float value) {
254     _writeByte(trace::TYPE_FLOAT);
255     _writeFloat(value);
256 }
257
258 void Writer::writeDouble(double value) {
259     _writeByte(trace::TYPE_DOUBLE);
260     _writeDouble(value);
261 }
262
263 void Writer::writeString(const char *str) {
264     if (!str) {
265         Writer::writeNull();
266         return;
267     }
268     _writeByte(trace::TYPE_STRING);
269     _writeString(str);
270 }
271
272 void Writer::writeString(const char *str, size_t len) {
273     if (!str) {
274         Writer::writeNull();
275         return;
276     }
277     _writeByte(trace::TYPE_STRING);
278     _writeUInt(len);
279     _write(str, len);
280 }
281
282 void Writer::writeWString(const wchar_t *str) {
283     if (!str) {
284         Writer::writeNull();
285         return;
286     }
287     _writeByte(trace::TYPE_STRING);
288     _writeString("<wide-string>");
289 }
290
291 void Writer::writeBlob(const void *data, size_t size) {
292     if (!data) {
293         Writer::writeNull();
294         return;
295     }
296     _writeByte(trace::TYPE_BLOB);
297     _writeUInt(size);
298     if (size) {
299         _write(data, size);
300     }
301 }
302
303 void Writer::writeEnum(const EnumSig *sig, signed long long value) {
304     _writeByte(trace::TYPE_ENUM);
305     _writeUInt(sig->id);
306     if (!lookup(enums, sig->id)) {
307         _writeUInt(sig->num_values);
308         for (unsigned i = 0; i < sig->num_values; ++i) {
309             _writeString(sig->values[i].name);
310             writeSInt(sig->values[i].value);
311         }
312         enums[sig->id] = true;
313     }
314     writeSInt(value);
315 }
316
317 void Writer::writeBitmask(const BitmaskSig *sig, unsigned long long value) {
318     _writeByte(trace::TYPE_BITMASK);
319     _writeUInt(sig->id);
320     if (!lookup(bitmasks, sig->id)) {
321         _writeUInt(sig->num_flags);
322         for (unsigned i = 0; i < sig->num_flags; ++i) {
323             if (i != 0 && sig->flags[i].value == 0) {
324                 os::log("apitrace: warning: sig %s is zero but is not first flag\n", sig->flags[i].name);
325             }
326             _writeString(sig->flags[i].name);
327             _writeUInt(sig->flags[i].value);
328         }
329         bitmasks[sig->id] = true;
330     }
331     _writeUInt(value);
332 }
333
334 void Writer::writeNull(void) {
335     _writeByte(trace::TYPE_NULL);
336 }
337
338 void Writer::writePointer(unsigned long long addr) {
339     if (!addr) {
340         Writer::writeNull();
341         return;
342     }
343     _writeByte(trace::TYPE_OPAQUE);
344     _writeUInt(addr);
345 }
346
347
348 } /* namespace trace */
349