1 /**************************************************************************
3 * Copyright 2007-2009 VMware, Inc.
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
24 **************************************************************************/
35 #include "trace_file.hpp"
36 #include "trace_writer.hpp"
37 #include "trace_format.hpp"
45 m_file = File::createSnappy();
62 Writer::open(const char *filename) {
65 if (!m_file->open(filename, File::Write)) {
76 _writeUInt(TRACE_VERSION);
82 Writer::_write(const void *sBuffer, size_t dwBytesToWrite) {
83 m_file->write(sBuffer, dwBytesToWrite);
87 Writer::_writeByte(char c) {
92 Writer::_writeUInt(unsigned long long value) {
93 char buf[2 * sizeof value];
98 assert(len < sizeof buf);
99 buf[len] = 0x80 | (value & 0x7f);
105 buf[len - 1] &= 0x7f;
111 Writer::_writeFloat(float value) {
112 assert(sizeof value == 4);
113 _write((const char *)&value, sizeof value);
117 Writer::_writeDouble(double value) {
118 assert(sizeof value == 8);
119 _write((const char *)&value, sizeof value);
123 Writer::_writeString(const char *str) {
124 size_t len = strlen(str);
129 inline bool lookup(std::vector<bool> &map, size_t index) {
130 if (index >= map.size()) {
131 map.resize(index + 1);
138 void Writer::beginBacktrace(unsigned num_frames) {
140 _writeByte(trace::CALL_BACKTRACE);
141 _writeUInt(num_frames);
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);
152 if (frame->function != NULL) {
153 _writeByte(trace::BACKTRACE_FUNCTION);
154 _writeString(frame->function);
156 if (frame->filename != NULL) {
157 _writeByte(trace::BACKTRACE_FILENAME);
158 _writeString(frame->filename);
160 if (frame->linenumber >= 0) {
161 _writeByte(trace::BACKTRACE_LINENUMBER);
162 _writeUInt(frame->linenumber);
164 if (frame->offset >= 0) {
165 _writeByte(trace::BACKTRACE_OFFSET);
166 _writeUInt(frame->offset);
168 _writeByte(trace::BACKTRACE_END);
169 frames[frame->id] = true;
173 unsigned Writer::beginEnter(const FunctionSig *sig, unsigned thread_id) {
174 _writeByte(trace::EVENT_ENTER);
175 _writeUInt(thread_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]);
183 functions[sig->id] = true;
189 void Writer::endEnter(void) {
190 _writeByte(trace::CALL_END);
193 void Writer::beginLeave(unsigned call) {
194 _writeByte(trace::EVENT_LEAVE);
198 void Writer::endLeave(void) {
199 _writeByte(trace::CALL_END);
202 void Writer::beginArg(unsigned index) {
203 _writeByte(trace::CALL_ARG);
207 void Writer::beginReturn(void) {
208 _writeByte(trace::CALL_RET);
211 void Writer::beginArray(size_t length) {
212 _writeByte(trace::TYPE_ARRAY);
216 void Writer::beginStruct(const StructSig *sig) {
217 _writeByte(trace::TYPE_STRUCT);
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]);
225 structs[sig->id] = true;
229 void Writer::beginRepr(void) {
230 _writeByte(trace::TYPE_REPR);
233 void Writer::writeBool(bool value) {
234 _writeByte(value ? trace::TYPE_TRUE : trace::TYPE_FALSE);
237 void Writer::writeSInt(signed long long value) {
239 _writeByte(trace::TYPE_SINT);
242 _writeByte(trace::TYPE_UINT);
247 void Writer::writeUInt(unsigned long long value) {
248 _writeByte(trace::TYPE_UINT);
252 void Writer::writeFloat(float value) {
253 _writeByte(trace::TYPE_FLOAT);
257 void Writer::writeDouble(double value) {
258 _writeByte(trace::TYPE_DOUBLE);
262 void Writer::writeString(const char *str) {
267 _writeByte(trace::TYPE_STRING);
271 void Writer::writeString(const char *str, size_t len) {
276 _writeByte(trace::TYPE_STRING);
281 void Writer::writeWString(const wchar_t *str) {
286 _writeByte(trace::TYPE_STRING);
287 _writeString("<wide-string>");
290 void Writer::writeBlob(const void *data, size_t size) {
295 _writeByte(trace::TYPE_BLOB);
302 void Writer::writeEnum(const EnumSig *sig, signed long long value) {
303 _writeByte(trace::TYPE_ENUM);
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);
311 enums[sig->id] = true;
316 void Writer::writeBitmask(const BitmaskSig *sig, unsigned long long value) {
317 _writeByte(trace::TYPE_BITMASK);
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);
325 _writeString(sig->flags[i].name);
326 _writeUInt(sig->flags[i].value);
328 bitmasks[sig->id] = true;
333 void Writer::writeNull(void) {
334 _writeByte(trace::TYPE_NULL);
337 void Writer::writePointer(unsigned long long addr) {
342 _writeByte(trace::TYPE_OPAQUE);
347 } /* namespace trace */