]> git.cworth.org Git - apitrace/blob - common/trace_writer.cpp
Remove FunctionSig::backtrace member.
[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
76     _writeUInt(TRACE_VERSION);
77
78     return true;
79 }
80
81 void inline
82 Writer::_write(const void *sBuffer, size_t dwBytesToWrite) {
83     m_file->write(sBuffer, dwBytesToWrite);
84 }
85
86 void inline
87 Writer::_writeByte(char c) {
88     _write(&c, 1);
89 }
90
91 void inline
92 Writer::_writeUInt(unsigned long long value) {
93     char buf[2 * sizeof value];
94     unsigned len;
95
96     len = 0;
97     do {
98         assert(len < sizeof buf);
99         buf[len] = 0x80 | (value & 0x7f);
100         value >>= 7;
101         ++len;
102     } while (value);
103
104     assert(len);
105     buf[len - 1] &= 0x7f;
106
107     _write(buf, len);
108 }
109
110 void inline
111 Writer::_writeFloat(float value) {
112     assert(sizeof value == 4);
113     _write((const char *)&value, sizeof value);
114 }
115
116 void inline
117 Writer::_writeDouble(double value) {
118     assert(sizeof value == 8);
119     _write((const char *)&value, sizeof value);
120 }
121
122 void inline
123 Writer::_writeString(const char *str) {
124     size_t len = strlen(str);
125     _writeUInt(len);
126     _write(str, len);
127 }
128
129 inline bool lookup(std::vector<bool> &map, size_t index) {
130     if (index >= map.size()) {
131         map.resize(index + 1);
132         return false;
133     } else {
134         return map[index];
135     }
136 }
137
138 void Writer::writeBacktrace(std::vector<RawStackFrame> backtrace) {
139
140     for (int i = 0; i < backtrace.size(); i++) {
141         beginStackFrame();
142         if (backtrace[i].module != NULL) {
143             beginStackFrameModule();
144             writeString(backtrace[i].module);
145             endStackFrameModule();
146         }
147         if (backtrace[i].function != NULL) {
148             beginStackFrameFunction();
149             writeString(backtrace[i].function);
150             endStackFrameFunction();
151         }
152         if (backtrace[i].filename != NULL) {
153             beginStackFrameFilename();
154             writeString(backtrace[i].filename);
155             endStackFrameFilename();
156         }
157         if (backtrace[i].linenumber != NULL) {
158             beginStackFrameLinenumber();
159             writeString(backtrace[i].linenumber);
160             endStackFrameLinenumber();
161         }
162         if (backtrace[i].offset != NULL) {
163             beginStackFrameOffset();
164             writeString(backtrace[i].offset);
165             endStackFrameOffset();
166         }
167         endStackFrame();
168     }
169 }
170
171 void Writer::beginBacktrace(void ) {
172     _writeByte(trace::CALL_BACKTRACE);
173 }
174
175 void Writer::endBacktrace(void ) {
176     _writeByte(trace::CALL_BACKTRACE_END);
177 }
178
179 void Writer::beginStackFrame(void ) {
180     _writeByte(trace::CALL_BACKTRACE_FRAME);
181 }
182
183 void Writer::beginStackFrameModule(void ) {
184     _writeByte(trace::CALL_BACKTRACE_MODULE);
185 }
186
187 void Writer::beginStackFrameFunction(void ) {
188     _writeByte(trace::CALL_BACKTRACE_FUNCTION);
189 }
190
191 void Writer::beginStackFrameFilename(void ) {
192     _writeByte(trace::CALL_BACKTRACE_FILENAME);
193 }
194
195 void Writer::beginStackFrameLinenumber(void ) {
196     _writeByte(trace::CALL_BACKTRACE_LINENUMBER);
197 }
198
199 void Writer::beginStackFrameOffset(void ) {
200     _writeByte(trace::CALL_BACKTRACE_OFFSET);
201 }
202
203 unsigned Writer::beginEnter(const FunctionSig *sig, unsigned thread_id) {
204     _writeByte(trace::EVENT_ENTER);
205     _writeUInt(thread_id);
206     _writeUInt(sig->id);
207     if (!lookup(functions, sig->id)) {
208         _writeString(sig->name);
209         _writeUInt(sig->num_args);
210         for (unsigned i = 0; i < sig->num_args; ++i) {
211             _writeString(sig->arg_names[i]);
212         }
213         functions[sig->id] = true;
214     }
215
216     return call_no++;
217 }
218
219 void Writer::endEnter(void) {
220     _writeByte(trace::CALL_END);
221 }
222
223 void Writer::beginLeave(unsigned call) {
224     _writeByte(trace::EVENT_LEAVE);
225     _writeUInt(call);
226 }
227
228 void Writer::endLeave(void) {
229     _writeByte(trace::CALL_END);
230 }
231
232 void Writer::beginArg(unsigned index) {
233     _writeByte(trace::CALL_ARG);
234     _writeUInt(index);
235 }
236
237 void Writer::beginReturn(void) {
238     _writeByte(trace::CALL_RET);
239 }
240
241 void Writer::beginArray(size_t length) {
242     _writeByte(trace::TYPE_ARRAY);
243     _writeUInt(length);
244 }
245
246 void Writer::beginStruct(const StructSig *sig) {
247     _writeByte(trace::TYPE_STRUCT);
248     _writeUInt(sig->id);
249     if (!lookup(structs, sig->id)) {
250         _writeString(sig->name);
251         _writeUInt(sig->num_members);
252         for (unsigned i = 0; i < sig->num_members; ++i) {
253             _writeString(sig->member_names[i]);
254         }
255         structs[sig->id] = true;
256     }
257 }
258
259 void Writer::beginRepr(void) {
260     _writeByte(trace::TYPE_REPR);
261 }
262
263 void Writer::writeBool(bool value) {
264     _writeByte(value ? trace::TYPE_TRUE : trace::TYPE_FALSE);
265 }
266
267 void Writer::writeSInt(signed long long value) {
268     if (value < 0) {
269         _writeByte(trace::TYPE_SINT);
270         _writeUInt(-value);
271     } else {
272         _writeByte(trace::TYPE_UINT);
273         _writeUInt(value);
274     }
275 }
276
277 void Writer::writeUInt(unsigned long long value) {
278     _writeByte(trace::TYPE_UINT);
279     _writeUInt(value);
280 }
281
282 void Writer::writeFloat(float value) {
283     _writeByte(trace::TYPE_FLOAT);
284     _writeFloat(value);
285 }
286
287 void Writer::writeDouble(double value) {
288     _writeByte(trace::TYPE_DOUBLE);
289     _writeDouble(value);
290 }
291
292 void Writer::writeString(const char *str) {
293     if (!str) {
294         Writer::writeNull();
295         return;
296     }
297     _writeByte(trace::TYPE_STRING);
298     _writeString(str);
299 }
300
301 void Writer::writeString(const char *str, size_t len) {
302     if (!str) {
303         Writer::writeNull();
304         return;
305     }
306     _writeByte(trace::TYPE_STRING);
307     _writeUInt(len);
308     _write(str, len);
309 }
310
311 void Writer::writeWString(const wchar_t *str) {
312     if (!str) {
313         Writer::writeNull();
314         return;
315     }
316     _writeByte(trace::TYPE_STRING);
317     _writeString("<wide-string>");
318 }
319
320 void Writer::writeBlob(const void *data, size_t size) {
321     if (!data) {
322         Writer::writeNull();
323         return;
324     }
325     _writeByte(trace::TYPE_BLOB);
326     _writeUInt(size);
327     if (size) {
328         _write(data, size);
329     }
330 }
331
332 void Writer::writeEnum(const EnumSig *sig, signed long long value) {
333     _writeByte(trace::TYPE_ENUM);
334     _writeUInt(sig->id);
335     if (!lookup(enums, sig->id)) {
336         _writeUInt(sig->num_values);
337         for (unsigned i = 0; i < sig->num_values; ++i) {
338             _writeString(sig->values[i].name);
339             writeSInt(sig->values[i].value);
340         }
341         enums[sig->id] = true;
342     }
343     writeSInt(value);
344 }
345
346 void Writer::writeBitmask(const BitmaskSig *sig, unsigned long long value) {
347     _writeByte(trace::TYPE_BITMASK);
348     _writeUInt(sig->id);
349     if (!lookup(bitmasks, sig->id)) {
350         _writeUInt(sig->num_flags);
351         for (unsigned i = 0; i < sig->num_flags; ++i) {
352             if (i != 0 && sig->flags[i].value == 0) {
353                 os::log("apitrace: warning: sig %s is zero but is not first flag\n", sig->flags[i].name);
354             }
355             _writeString(sig->flags[i].name);
356             _writeUInt(sig->flags[i].value);
357         }
358         bitmasks[sig->id] = true;
359     }
360     _writeUInt(value);
361 }
362
363 void Writer::writeNull(void) {
364     _writeByte(trace::TYPE_NULL);
365 }
366
367 void Writer::writePointer(unsigned long long addr) {
368     if (!addr) {
369         Writer::writeNull();
370         return;
371     }
372     _writeByte(trace::TYPE_OPAQUE);
373     _writeUInt(addr);
374 }
375
376
377 } /* namespace trace */
378