]> git.cworth.org Git - apitrace/blob - common/trace_writer.cpp
Backtrace via call detail
[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(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         sig->backtrace = backtrace_is_needed(sig->name);
209         _writeString(sig->name);
210         _writeUInt(sig->num_args);
211         for (unsigned i = 0; i < sig->num_args; ++i) {
212             _writeString(sig->arg_names[i]);
213         }
214         functions[sig->id] = true;
215     }
216
217     return call_no++;
218 }
219
220 void Writer::endEnter(void) {
221     _writeByte(trace::CALL_END);
222 }
223
224 void Writer::beginLeave(unsigned call) {
225     _writeByte(trace::EVENT_LEAVE);
226     _writeUInt(call);
227 }
228
229 void Writer::endLeave(void) {
230     _writeByte(trace::CALL_END);
231 }
232
233 void Writer::beginArg(unsigned index) {
234     _writeByte(trace::CALL_ARG);
235     _writeUInt(index);
236 }
237
238 void Writer::beginReturn(void) {
239     _writeByte(trace::CALL_RET);
240 }
241
242 void Writer::beginArray(size_t length) {
243     _writeByte(trace::TYPE_ARRAY);
244     _writeUInt(length);
245 }
246
247 void Writer::beginStruct(const StructSig *sig) {
248     _writeByte(trace::TYPE_STRUCT);
249     _writeUInt(sig->id);
250     if (!lookup(structs, sig->id)) {
251         _writeString(sig->name);
252         _writeUInt(sig->num_members);
253         for (unsigned i = 0; i < sig->num_members; ++i) {
254             _writeString(sig->member_names[i]);
255         }
256         structs[sig->id] = true;
257     }
258 }
259
260 void Writer::beginRepr(void) {
261     _writeByte(trace::TYPE_REPR);
262 }
263
264 void Writer::writeBool(bool value) {
265     _writeByte(value ? trace::TYPE_TRUE : trace::TYPE_FALSE);
266 }
267
268 void Writer::writeSInt(signed long long value) {
269     if (value < 0) {
270         _writeByte(trace::TYPE_SINT);
271         _writeUInt(-value);
272     } else {
273         _writeByte(trace::TYPE_UINT);
274         _writeUInt(value);
275     }
276 }
277
278 void Writer::writeUInt(unsigned long long value) {
279     _writeByte(trace::TYPE_UINT);
280     _writeUInt(value);
281 }
282
283 void Writer::writeFloat(float value) {
284     _writeByte(trace::TYPE_FLOAT);
285     _writeFloat(value);
286 }
287
288 void Writer::writeDouble(double value) {
289     _writeByte(trace::TYPE_DOUBLE);
290     _writeDouble(value);
291 }
292
293 void Writer::writeString(const char *str) {
294     if (!str) {
295         Writer::writeNull();
296         return;
297     }
298     _writeByte(trace::TYPE_STRING);
299     _writeString(str);
300 }
301
302 void Writer::writeString(const char *str, size_t len) {
303     if (!str) {
304         Writer::writeNull();
305         return;
306     }
307     _writeByte(trace::TYPE_STRING);
308     _writeUInt(len);
309     _write(str, len);
310 }
311
312 void Writer::writeWString(const wchar_t *str) {
313     if (!str) {
314         Writer::writeNull();
315         return;
316     }
317     _writeByte(trace::TYPE_STRING);
318     _writeString("<wide-string>");
319 }
320
321 void Writer::writeBlob(const void *data, size_t size) {
322     if (!data) {
323         Writer::writeNull();
324         return;
325     }
326     _writeByte(trace::TYPE_BLOB);
327     _writeUInt(size);
328     if (size) {
329         _write(data, size);
330     }
331 }
332
333 void Writer::writeEnum(const EnumSig *sig, signed long long value) {
334     _writeByte(trace::TYPE_ENUM);
335     _writeUInt(sig->id);
336     if (!lookup(enums, sig->id)) {
337         _writeUInt(sig->num_values);
338         for (unsigned i = 0; i < sig->num_values; ++i) {
339             _writeString(sig->values[i].name);
340             writeSInt(sig->values[i].value);
341         }
342         enums[sig->id] = true;
343     }
344     writeSInt(value);
345 }
346
347 void Writer::writeBitmask(const BitmaskSig *sig, unsigned long long value) {
348     _writeByte(trace::TYPE_BITMASK);
349     _writeUInt(sig->id);
350     if (!lookup(bitmasks, sig->id)) {
351         _writeUInt(sig->num_flags);
352         for (unsigned i = 0; i < sig->num_flags; ++i) {
353             if (i != 0 && sig->flags[i].value == 0) {
354                 os::log("apitrace: warning: sig %s is zero but is not first flag\n", sig->flags[i].name);
355             }
356             _writeString(sig->flags[i].name);
357             _writeUInt(sig->flags[i].value);
358         }
359         bitmasks[sig->id] = true;
360     }
361     _writeUInt(value);
362 }
363
364 void Writer::writeNull(void) {
365     _writeByte(trace::TYPE_NULL);
366 }
367
368 void Writer::writePointer(unsigned long long addr) {
369     if (!addr) {
370         Writer::writeNull();
371         return;
372     }
373     _writeByte(trace::TYPE_OPAQUE);
374     _writeUInt(addr);
375 }
376
377
378 } /* namespace trace */
379