diff options
author | José Fonseca <jose.r.fonseca@gmail.com> | 2011-09-21 07:46:50 +0100 |
---|---|---|
committer | José Fonseca <jose.r.fonseca@gmail.com> | 2011-09-21 07:46:50 +0100 |
commit | a8c164caecc408462d3e4c1626c87ab9974f6a48 (patch) | |
tree | 49dcbaab533034b6729fc04206f5e99645cf411e /common/trace_writer.cpp | |
parent | ee2073911c1f76715427ef0c031bea7b8483ea97 (diff) |
Put all common code in a subdirectory.
Diffstat (limited to 'common/trace_writer.cpp')
-rw-r--r-- | common/trace_writer.cpp | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/common/trace_writer.cpp b/common/trace_writer.cpp new file mode 100644 index 0000000..5a5f1f7 --- /dev/null +++ b/common/trace_writer.cpp @@ -0,0 +1,303 @@ +/************************************************************************** + * + * Copyright 2007-2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#include <assert.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "os.hpp" +#include "trace_writer.hpp" +#include "trace_snappyfile.hpp" +#include "trace_format.hpp" + + +namespace Trace { + + +Writer::Writer() : + call_no(0) +{ + m_file = new Trace::SnappyFile; + close(); +} + +Writer::~Writer() +{ + close(); + delete m_file; + m_file = NULL; +} + +void +Writer::close(void) { + m_file->close(); +} + +bool +Writer::open(const char *filename) { + close(); + + if (!m_file->open(filename, File::Write)) { + return false; + } + + call_no = 0; + functions.clear(); + structs.clear(); + enums.clear(); + bitmasks.clear(); + + _writeUInt(TRACE_VERSION); + + return true; +} + +void inline +Writer::_write(const void *sBuffer, size_t dwBytesToWrite) { + m_file->write(sBuffer, dwBytesToWrite); +} + +void inline +Writer::_writeByte(char c) { + _write(&c, 1); +} + +void inline +Writer::_writeUInt(unsigned long long value) { + char buf[2 * sizeof value]; + unsigned len; + + len = 0; + do { + assert(len < sizeof buf); + buf[len] = 0x80 | (value & 0x7f); + value >>= 7; + ++len; + } while (value); + + assert(len); + buf[len - 1] &= 0x7f; + + _write(buf, len); +} + +void inline +Writer::_writeFloat(float value) { + assert(sizeof value == 4); + _write((const char *)&value, sizeof value); +} + +void inline +Writer::_writeDouble(double value) { + assert(sizeof value == 8); + _write((const char *)&value, sizeof value); +} + +void inline +Writer::_writeString(const char *str) { + size_t len = strlen(str); + _writeUInt(len); + _write(str, len); +} + +inline bool lookup(std::vector<bool> &map, size_t index) { + if (index >= map.size()) { + map.resize(index + 1); + return false; + } else { + return map[index]; + } +} + +unsigned Writer::beginEnter(const FunctionSig *sig) { + _writeByte(Trace::EVENT_ENTER); + _writeUInt(sig->id); + if (!lookup(functions, sig->id)) { + _writeString(sig->name); + _writeUInt(sig->num_args); + for (unsigned i = 0; i < sig->num_args; ++i) { + _writeString(sig->arg_names[i]); + } + functions[sig->id] = true; + } + + return call_no++; +} + +void Writer::endEnter(void) { + _writeByte(Trace::CALL_END); +} + +void Writer::beginLeave(unsigned call) { + _writeByte(Trace::EVENT_LEAVE); + _writeUInt(call); +} + +void Writer::endLeave(void) { + _writeByte(Trace::CALL_END); +} + +void Writer::beginArg(unsigned index) { + _writeByte(Trace::CALL_ARG); + _writeUInt(index); +} + +void Writer::beginReturn(void) { + _writeByte(Trace::CALL_RET); +} + +void Writer::beginArray(size_t length) { + _writeByte(Trace::TYPE_ARRAY); + _writeUInt(length); +} + +void Writer::beginStruct(const StructSig *sig) { + _writeByte(Trace::TYPE_STRUCT); + _writeUInt(sig->id); + if (!lookup(structs, sig->id)) { + _writeString(sig->name); + _writeUInt(sig->num_members); + for (unsigned i = 0; i < sig->num_members; ++i) { + _writeString(sig->member_names[i]); + } + structs[sig->id] = true; + } +} + +void Writer::writeBool(bool value) { + _writeByte(value ? Trace::TYPE_TRUE : Trace::TYPE_FALSE); +} + +void Writer::writeSInt(signed long long value) { + if (value < 0) { + _writeByte(Trace::TYPE_SINT); + _writeUInt(-value); + } else { + _writeByte(Trace::TYPE_UINT); + _writeUInt(value); + } +} + +void Writer::writeUInt(unsigned long long value) { + _writeByte(Trace::TYPE_UINT); + _writeUInt(value); +} + +void Writer::writeFloat(float value) { + _writeByte(Trace::TYPE_FLOAT); + _writeFloat(value); +} + +void Writer::writeDouble(double value) { + _writeByte(Trace::TYPE_DOUBLE); + _writeDouble(value); +} + +void Writer::writeString(const char *str) { + if (!str) { + Writer::writeNull(); + return; + } + _writeByte(Trace::TYPE_STRING); + _writeString(str); +} + +void Writer::writeString(const char *str, size_t len) { + if (!str) { + Writer::writeNull(); + return; + } + _writeByte(Trace::TYPE_STRING); + _writeUInt(len); + _write(str, len); +} + +void Writer::writeWString(const wchar_t *str) { + if (!str) { + Writer::writeNull(); + return; + } + _writeByte(Trace::TYPE_STRING); + _writeString("<wide-string>"); +} + +void Writer::writeBlob(const void *data, size_t size) { + if (!data) { + Writer::writeNull(); + return; + } + _writeByte(Trace::TYPE_BLOB); + _writeUInt(size); + if (size) { + _write(data, size); + } +} + +void Writer::writeEnum(const EnumSig *sig) { + _writeByte(Trace::TYPE_ENUM); + _writeUInt(sig->id); + if (!lookup(enums, sig->id)) { + _writeString(sig->name); + Writer::writeSInt(sig->value); + enums[sig->id] = true; + } +} + +void Writer::writeBitmask(const BitmaskSig *sig, unsigned long long value) { + _writeByte(Trace::TYPE_BITMASK); + _writeUInt(sig->id); + if (!lookup(bitmasks, sig->id)) { + _writeUInt(sig->num_flags); + for (unsigned i = 0; i < sig->num_flags; ++i) { + if (i != 0 && sig->flags[i].value == 0) { + OS::DebugMessage("apitrace: warning: sig %s is zero but is not first flag\n", sig->flags[i].name); + } + _writeString(sig->flags[i].name); + _writeUInt(sig->flags[i].value); + } + bitmasks[sig->id] = true; + } + _writeUInt(value); +} + +void Writer::writeNull(void) { + _writeByte(Trace::TYPE_NULL); +} + +void Writer::writeOpaque(const void *addr) { + if (!addr) { + Writer::writeNull(); + return; + } + _writeByte(Trace::TYPE_OPAQUE); + _writeUInt((size_t)addr); +} + + +} /* namespace Trace */ + |