]> git.cworth.org Git - apitrace/blob - common/trace_writer.cpp
common: rename trace_backtrace.* -> os_backtrace.*
[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
39 namespace trace {
40
41
42 Writer::Writer() :
43     call_no(0)
44 {
45     m_file = File::createSnappy();
46     close();
47 }
48
49 Writer::~Writer()
50 {
51     close();
52     delete m_file;
53     m_file = NULL;
54 }
55
56 void
57 Writer::close(void) {
58     m_file->close();
59 }
60
61 bool
62 Writer::open(const char *filename) {
63     close();
64
65     if (!m_file->open(filename, File::Write)) {
66         return false;
67     }
68
69     call_no = 0;
70     functions.clear();
71     structs.clear();
72     enums.clear();
73     bitmasks.clear();
74     frames.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::beginBacktrace(unsigned num_frames) {
139     if (num_frames) {
140         _writeByte(trace::CALL_BACKTRACE);
141         _writeUInt(num_frames);
142     }
143 }
144
145 void Writer::writeStackFrame(const RawStackFrame *frame) {
146     _writeUInt(frame->id);
147     if (!lookup(frames, frame->id)) {
148         if (frame->module != NULL) {
149             _writeByte(trace::BACKTRACE_MODULE);
150             _writeString(frame->module);
151         }
152         if (frame->function != NULL) {
153             _writeByte(trace::BACKTRACE_FUNCTION);
154             _writeString(frame->function);
155         }
156         if (frame->filename != NULL) {
157             _writeByte(trace::BACKTRACE_FILENAME);
158             _writeString(frame->filename);
159         }
160         if (frame->linenumber >= 0) {
161             _writeByte(trace::BACKTRACE_LINENUMBER);
162             _writeUInt(frame->linenumber);
163         }
164         if (frame->offset >= 0) {
165             _writeByte(trace::BACKTRACE_OFFSET);
166             _writeUInt(frame->offset);
167         }
168         _writeByte(trace::BACKTRACE_END);
169         frames[frame->id] = true;
170     }
171 }
172
173 unsigned Writer::beginEnter(const FunctionSig *sig, unsigned thread_id) {
174     _writeByte(trace::EVENT_ENTER);
175     _writeUInt(thread_id);
176     _writeUInt(sig->id);
177     if (!lookup(functions, sig->id)) {
178         _writeString(sig->name);
179         _writeUInt(sig->num_args);
180         for (unsigned i = 0; i < sig->num_args; ++i) {
181             _writeString(sig->arg_names[i]);
182         }
183         functions[sig->id] = true;
184     }
185
186     return call_no++;
187 }
188
189 void Writer::endEnter(void) {
190     _writeByte(trace::CALL_END);
191 }
192
193 void Writer::beginLeave(unsigned call) {
194     _writeByte(trace::EVENT_LEAVE);
195     _writeUInt(call);
196 }
197
198 void Writer::endLeave(void) {
199     _writeByte(trace::CALL_END);
200 }
201
202 void Writer::beginArg(unsigned index) {
203     _writeByte(trace::CALL_ARG);
204     _writeUInt(index);
205 }
206
207 void Writer::beginReturn(void) {
208     _writeByte(trace::CALL_RET);
209 }
210
211 void Writer::beginArray(size_t length) {
212     _writeByte(trace::TYPE_ARRAY);
213     _writeUInt(length);
214 }
215
216 void Writer::beginStruct(const StructSig *sig) {
217     _writeByte(trace::TYPE_STRUCT);
218     _writeUInt(sig->id);
219     if (!lookup(structs, sig->id)) {
220         _writeString(sig->name);
221         _writeUInt(sig->num_members);
222         for (unsigned i = 0; i < sig->num_members; ++i) {
223             _writeString(sig->member_names[i]);
224         }
225         structs[sig->id] = true;
226     }
227 }
228
229 void Writer::beginRepr(void) {
230     _writeByte(trace::TYPE_REPR);
231 }
232
233 void Writer::writeBool(bool value) {
234     _writeByte(value ? trace::TYPE_TRUE : trace::TYPE_FALSE);
235 }
236
237 void Writer::writeSInt(signed long long value) {
238     if (value < 0) {
239         _writeByte(trace::TYPE_SINT);
240         _writeUInt(-value);
241     } else {
242         _writeByte(trace::TYPE_UINT);
243         _writeUInt(value);
244     }
245 }
246
247 void Writer::writeUInt(unsigned long long value) {
248     _writeByte(trace::TYPE_UINT);
249     _writeUInt(value);
250 }
251
252 void Writer::writeFloat(float value) {
253     _writeByte(trace::TYPE_FLOAT);
254     _writeFloat(value);
255 }
256
257 void Writer::writeDouble(double value) {
258     _writeByte(trace::TYPE_DOUBLE);
259     _writeDouble(value);
260 }
261
262 void Writer::writeString(const char *str) {
263     if (!str) {
264         Writer::writeNull();
265         return;
266     }
267     _writeByte(trace::TYPE_STRING);
268     _writeString(str);
269 }
270
271 void Writer::writeString(const char *str, size_t len) {
272     if (!str) {
273         Writer::writeNull();
274         return;
275     }
276     _writeByte(trace::TYPE_STRING);
277     _writeUInt(len);
278     _write(str, len);
279 }
280
281 void Writer::writeWString(const wchar_t *str) {
282     if (!str) {
283         Writer::writeNull();
284         return;
285     }
286     _writeByte(trace::TYPE_STRING);
287     _writeString("<wide-string>");
288 }
289
290 void Writer::writeBlob(const void *data, size_t size) {
291     if (!data) {
292         Writer::writeNull();
293         return;
294     }
295     _writeByte(trace::TYPE_BLOB);
296     _writeUInt(size);
297     if (size) {
298         _write(data, size);
299     }
300 }
301
302 void Writer::writeEnum(const EnumSig *sig, signed long long value) {
303     _writeByte(trace::TYPE_ENUM);
304     _writeUInt(sig->id);
305     if (!lookup(enums, sig->id)) {
306         _writeUInt(sig->num_values);
307         for (unsigned i = 0; i < sig->num_values; ++i) {
308             _writeString(sig->values[i].name);
309             writeSInt(sig->values[i].value);
310         }
311         enums[sig->id] = true;
312     }
313     writeSInt(value);
314 }
315
316 void Writer::writeBitmask(const BitmaskSig *sig, unsigned long long value) {
317     _writeByte(trace::TYPE_BITMASK);
318     _writeUInt(sig->id);
319     if (!lookup(bitmasks, sig->id)) {
320         _writeUInt(sig->num_flags);
321         for (unsigned i = 0; i < sig->num_flags; ++i) {
322             if (i != 0 && sig->flags[i].value == 0) {
323                 os::log("apitrace: warning: sig %s is zero but is not first flag\n", sig->flags[i].name);
324             }
325             _writeString(sig->flags[i].name);
326             _writeUInt(sig->flags[i].value);
327         }
328         bitmasks[sig->id] = true;
329     }
330     _writeUInt(value);
331 }
332
333 void Writer::writeNull(void) {
334     _writeByte(trace::TYPE_NULL);
335 }
336
337 void Writer::writePointer(unsigned long long addr) {
338     if (!addr) {
339         Writer::writeNull();
340         return;
341     }
342     _writeByte(trace::TYPE_OPAQUE);
343     _writeUInt(addr);
344 }
345
346
347 } /* namespace trace */
348