]> git.cworth.org Git - apitrace/blob - trace_writer.cpp
Merge branch 'master' into compression
[apitrace] / 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
33 #include "os.hpp"
34 #include "trace_writer.hpp"
35 #include "trace_file.hpp"
36 #include "trace_format.hpp"
37
38
39 namespace Trace {
40
41
42 Writer::Writer() :
43     call_no(0)
44 {
45     m_file = new Trace::SnappyFile;
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
75     _writeUInt(TRACE_VERSION);
76
77     return true;
78 }
79
80 void inline
81 Writer::_write(const void *sBuffer, size_t dwBytesToWrite) {
82     m_file->write(sBuffer, dwBytesToWrite);
83 }
84
85 void inline
86 Writer::_writeByte(char c) {
87     _write(&c, 1);
88 }
89
90 void inline
91 Writer::_writeUInt(unsigned long long value) {
92     char buf[2 * sizeof value];
93     unsigned len;
94
95     len = 0;
96     do {
97         assert(len < sizeof buf);
98         buf[len] = 0x80 | (value & 0x7f);
99         value >>= 7;
100         ++len;
101     } while (value);
102
103     assert(len);
104     buf[len - 1] &= 0x7f;
105
106     _write(buf, len);
107 }
108
109 void inline
110 Writer::_writeFloat(float value) {
111     assert(sizeof value == 4);
112     _write((const char *)&value, sizeof value);
113 }
114
115 void inline
116 Writer::_writeDouble(double value) {
117     assert(sizeof value == 8);
118     _write((const char *)&value, sizeof value);
119 }
120
121 void inline
122 Writer::_writeString(const char *str) {
123     size_t len = strlen(str);
124     _writeUInt(len);
125     _write(str, len);
126 }
127
128 inline bool lookup(std::vector<bool> &map, size_t index) {
129     if (index >= map.size()) {
130         map.resize(index + 1);
131         return false;
132     } else {
133         return map[index];
134     }
135 }
136
137 unsigned Writer::beginEnter(const FunctionSig *sig) {
138     _writeByte(Trace::EVENT_ENTER);
139     _writeUInt(sig->id);
140     if (!lookup(functions, sig->id)) {
141         _writeString(sig->name);
142         _writeUInt(sig->num_args);
143         for (unsigned i = 0; i < sig->num_args; ++i) {
144             _writeString(sig->arg_names[i]);
145         }
146         functions[sig->id] = true;
147     }
148
149     return call_no++;
150 }
151
152 void Writer::endEnter(void) {
153     _writeByte(Trace::CALL_END);
154 }
155
156 void Writer::beginLeave(unsigned call) {
157     _writeByte(Trace::EVENT_LEAVE);
158     _writeUInt(call);
159 }
160
161 void Writer::endLeave(void) {
162     _writeByte(Trace::CALL_END);
163 }
164
165 void Writer::beginArg(unsigned index) {
166     _writeByte(Trace::CALL_ARG);
167     _writeUInt(index);
168 }
169
170 void Writer::beginReturn(void) {
171     _writeByte(Trace::CALL_RET);
172 }
173
174 void Writer::beginArray(size_t length) {
175     _writeByte(Trace::TYPE_ARRAY);
176     _writeUInt(length);
177 }
178
179 void Writer::beginStruct(const StructSig *sig) {
180     _writeByte(Trace::TYPE_STRUCT);
181     _writeUInt(sig->id);
182     if (!lookup(structs, sig->id)) {
183         _writeString(sig->name);
184         _writeUInt(sig->num_members);
185         for (unsigned i = 0; i < sig->num_members; ++i) {
186             _writeString(sig->member_names[i]);
187         }
188         structs[sig->id] = true;
189     }
190 }
191
192 void Writer::writeBool(bool value) {
193     _writeByte(value ? Trace::TYPE_TRUE : Trace::TYPE_FALSE);
194 }
195
196 void Writer::writeSInt(signed long long value) {
197     if (value < 0) {
198         _writeByte(Trace::TYPE_SINT);
199         _writeUInt(-value);
200     } else {
201         _writeByte(Trace::TYPE_UINT);
202         _writeUInt(value);
203     }
204 }
205
206 void Writer::writeUInt(unsigned long long value) {
207     _writeByte(Trace::TYPE_UINT);
208     _writeUInt(value);
209 }
210
211 void Writer::writeFloat(float value) {
212     _writeByte(Trace::TYPE_FLOAT);
213     _writeFloat(value);
214 }
215
216 void Writer::writeDouble(double value) {
217     _writeByte(Trace::TYPE_DOUBLE);
218     _writeDouble(value);
219 }
220
221 void Writer::writeString(const char *str) {
222     if (!str) {
223         Writer::writeNull();
224         return;
225     }
226     _writeByte(Trace::TYPE_STRING);
227     _writeString(str);
228 }
229
230 void Writer::writeString(const char *str, size_t len) {
231     if (!str) {
232         Writer::writeNull();
233         return;
234     }
235     _writeByte(Trace::TYPE_STRING);
236     _writeUInt(len);
237     _write(str, len);
238 }
239
240 void Writer::writeWString(const wchar_t *str) {
241     if (!str) {
242         Writer::writeNull();
243         return;
244     }
245     _writeByte(Trace::TYPE_STRING);
246     _writeString("<wide-string>");
247 }
248
249 void Writer::writeBlob(const void *data, size_t size) {
250     if (!data) {
251         Writer::writeNull();
252         return;
253     }
254     _writeByte(Trace::TYPE_BLOB);
255     _writeUInt(size);
256     if (size) {
257         _write(data, size);
258     }
259 }
260
261 void Writer::writeEnum(const EnumSig *sig) {
262     _writeByte(Trace::TYPE_ENUM);
263     _writeUInt(sig->id);
264     if (!lookup(enums, sig->id)) {
265         _writeString(sig->name);
266         Writer::writeSInt(sig->value);
267         enums[sig->id] = true;
268     }
269 }
270
271 void Writer::writeBitmask(const BitmaskSig *sig, unsigned long long value) {
272     _writeByte(Trace::TYPE_BITMASK);
273     _writeUInt(sig->id);
274     if (!lookup(bitmasks, sig->id)) {
275         _writeUInt(sig->num_flags);
276         for (unsigned i = 0; i < sig->num_flags; ++i) {
277             if (i != 0 && sig->flags[i].value == 0) {
278                 OS::DebugMessage("apitrace: warning: sig %s is zero but is not first flag\n", sig->flags[i].name);
279             }
280             _writeString(sig->flags[i].name);
281             _writeUInt(sig->flags[i].value);
282         }
283         bitmasks[sig->id] = true;
284     }
285     _writeUInt(value);
286 }
287
288 void Writer::writeNull(void) {
289     _writeByte(Trace::TYPE_NULL);
290 }
291
292 void Writer::writeOpaque(const void *addr) {
293     if (!addr) {
294         Writer::writeNull();
295         return;
296     }
297     _writeByte(Trace::TYPE_OPAQUE);
298     _writeUInt((size_t)addr);
299 }
300
301
302 } /* namespace Trace */
303