X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=trace_parser.hpp;h=1f87b6fed185c8959dd112a2aa4d2c3dce99f702;hb=e5592342cb5d8b357fb68946a9405542b517985a;hp=f008fb993401ec9cdbad4b7c8a97835fdeb88017;hpb=bb32c5e7bb3be07038c9f8cfc4559d34744bd3d8;p=apitrace diff --git a/trace_parser.hpp b/trace_parser.hpp index f008fb9..1f87b6f 100644 --- a/trace_parser.hpp +++ b/trace_parser.hpp @@ -27,380 +27,171 @@ #define _TRACE_PARSER_HPP_ -#include - #include -#include #include -#include - -#include +#include +#include "trace_file.hpp" #include "trace_format.hpp" #include "trace_model.hpp" -#define TRACE_VERBOSE 0 - - namespace Trace { - class Parser { protected: - gzFile file; + File *file; typedef std::list CallList; CallList calls; - typedef std::vector FunctionMap; + typedef std::vector FunctionMap; FunctionMap functions; - typedef std::vector StructMap; + typedef std::vector StructMap; StructMap structs; - typedef std::vector EnumMap; + typedef std::vector EnumMap; EnumMap enums; - typedef std::vector BitmaskMap; + typedef std::vector BitmaskMap; BitmaskMap bitmasks; + typedef std::set TraceOffsets; + TraceOffsets m_callSigOffsets; + TraceOffsets m_structSigOffsets; + TraceOffsets m_enumSigOffsets; + TraceOffsets m_bitmaskSigOffsets; + + typedef std::map CallNumOffsets; + CallNumOffsets m_callNumOffsets; + unsigned next_call_no; public: - static unsigned long long version; + unsigned long long version; - Parser() { - file = NULL; - next_call_no = 0; - } + Parser(); - ~Parser() { - close(); - } + ~Parser(); - bool open(const char *filename) { - file = gzopen(filename, "rb"); - if (!file) { - return false; - } + bool open(const char *filename); - version = read_uint(); - if (version > TRACE_VERSION) { - std::cerr << "error: unsupported format version" << version << "\n"; - return false; - } + void close(void); - return true; + Call *parse_call(void); + + bool supportsOffsets() const + { + return file->supportsOffsets(); } - void close(void) { - if (file) { - gzclose(file); - file = NULL; - } + File::Offset currentOffset() + { + return file->currentOffset(); } - Call *parse_call(void) { - do { - int c = read_byte(); - switch(c) { - case Trace::EVENT_ENTER: - parse_enter(); - break; - case Trace::EVENT_LEAVE: - return parse_leave(); - case Trace::EVENT_MESSAGE: - std::cerr << "message: " << read_string() << "\n"; - break; - default: - std::cerr << "error: unknown call detail " << c << "\n"; - assert(0); - /* fallthrough */ - case -1: - return NULL; - } - } while(true); + void setCurrentOffset(const File::Offset &offset) + { + file->setCurrentOffset(offset); } - /** - * Helper function to lookup an ID in a vector, resizing the vector if it doesn't fit. - */ - template - T *lookup(std::vector &map, size_t index) { - if (index >= map.size()) { - map.resize(index + 1); - return NULL; - } else { - return map[index]; - } + bool callWithSignature(const File::Offset &offset) const; + bool structWithSignature(const File::Offset &offset) const; + bool enumWithSignature(const File::Offset &offset) const; + bool bitmaskWithSignature(const File::Offset &offset) const; + + unsigned currentCallNumber() const + { + return next_call_no; } - void parse_enter(void) { - size_t id = read_uint(); + void setCurrentCallNumber(unsigned num) + { + next_call_no = num; + } - Call::Signature *sig = lookup(functions, id); - if (!sig) { - sig = new Call::Signature; - sig->name = read_string(); - unsigned size = read_uint(); - for (unsigned i = 0; i < size; ++i) { - sig->arg_names.push_back(read_string()); - } - functions[id] = sig; - } - assert(sig); + Call *scan_call(); - Call *call = new Call(sig); - call->no = next_call_no++; +protected: + void parse_enter(void); - parse_call_details(call); + Call *parse_leave(void); - calls.push_back(call); - } + bool parse_call_details(Call *call); - Call *parse_leave(void) { - unsigned call_no = read_uint(); - - Call *call = NULL; - for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) { - if ((*it)->no == call_no) { - call = *it; - calls.erase(it); - break; - } - } - assert(call); - if (!call) { - return NULL; - } - parse_call_details(call); - return call; - } + void parse_arg(Call *call); - void parse_call_details(Call *call) { - do { - int c = read_byte(); - switch(c) { - case Trace::CALL_END: - return; - case Trace::CALL_ARG: - parse_arg(call); - break; - case Trace::CALL_RET: - call->ret = parse_value(); - break; - default: - std::cerr << "error: unknown call detail " << c << "\n"; - assert(0); - /* fallthrough */ - case -1: - return; - } - } while(true); - } + Value *parse_value(void); - void parse_arg(Call *call) { - unsigned index = read_uint(); - Value *value = parse_value(); - if (index >= call->args.size()) { - call->args.resize(index + 1); - } - call->args[index] = value; - } + Value *parse_sint(); - Value *parse_value(void) { - int c; - c = read_byte(); - switch(c) { - case Trace::TYPE_NULL: - return new Null; - case Trace::TYPE_FALSE: - return new Bool(false); - case Trace::TYPE_TRUE: - return new Bool(true); - case Trace::TYPE_SINT: - return parse_sint(); - case Trace::TYPE_UINT: - return parse_uint(); - case Trace::TYPE_FLOAT: - return parse_float(); - case Trace::TYPE_DOUBLE: - return parse_double(); - case Trace::TYPE_STRING: - return parse_string(); - case Trace::TYPE_ENUM: - return parse_enum(); - case Trace::TYPE_BITMASK: - return parse_bitmask(); - case Trace::TYPE_ARRAY: - return parse_array(); - case Trace::TYPE_STRUCT: - return parse_struct(); - case Trace::TYPE_BLOB: - return parse_blob(); - case Trace::TYPE_OPAQUE: - return parse_opaque(); - default: - std::cerr << "error: unknown type " << c << "\n"; - assert(0); - return NULL; - } - } + Value *parse_uint(); - Value *parse_sint() { - return new SInt(-(signed long long)read_uint()); - } + Value *parse_float(); - Value *parse_uint() { - return new UInt(read_uint()); - } + Value *parse_double(); - Value *parse_float() { - float value; - gzread(file, &value, sizeof value); - return new Float(value); - } + Value *parse_string(); - Value *parse_double() { - double value; - gzread(file, &value, sizeof value); - return new Float(value); - } + Value *parse_enum(); - Value *parse_string() { - return new String(read_string()); - } + Value *parse_bitmask(); - Value *parse_enum() { - size_t id = read_uint(); - Enum::Signature *sig = lookup(enums, id); - if (!sig) { - std::string name = read_string(); - Value *value = parse_value(); - sig = new Enum::Signature(name, value); - enums[id] = sig; - } - assert(sig); - return new Enum(sig); - } + Value *parse_array(void); - Value *parse_bitmask() { - size_t id = read_uint(); - Bitmask::Signature *sig = lookup(bitmasks, id); - if (!sig) { - size_t size = read_uint(); - sig = new Bitmask::Signature(size); - for (Bitmask::Signature::iterator it = sig->begin(); it != sig->end(); ++it) { - it->first = read_string(); - it->second = read_uint(); - assert(it->second); - } - bitmasks[id] = sig; - } - assert(sig); - - unsigned long long value = read_uint(); - - return new Bitmask(sig, value); - } + Value *parse_blob(void); - Value *parse_array(void) { - size_t len = read_uint(); - Array *array = new Array(len); - for (size_t i = 0; i < len; ++i) { - array->values[i] = parse_value(); - } - return array; - } + Value *parse_struct(); - Value *parse_blob(void) { - size_t size = read_uint(); - Blob *blob = new Blob(size); - if (size) { - gzread(file, blob->buf, (unsigned)size); - } - return blob; - } + Value *parse_opaque(); - Value *parse_struct() { - size_t id = read_uint(); + const char * read_string(void); - Struct::Signature *sig = lookup(structs, id); - if (!sig) { - sig = new Struct::Signature; - sig->name = read_string(); - unsigned size = read_uint(); - for (unsigned i = 0; i < size; ++i) { - sig->member_names.push_back(read_string()); - } - structs[id] = sig; - } - assert(sig); + unsigned long long read_uint(void); - Struct *value = new Struct(sig); + inline int read_byte(void); - for (size_t i = 0; i < sig->member_names.size(); ++i) { - value->members[i] = parse_value(); - } +protected: + void scan_enter(void); - return value; - } + Call *scan_leave(void); - Value *parse_opaque() { - unsigned long long addr; - addr = read_uint(); - return new Pointer(addr); - } + bool scan_call_details(Call *call); - std::string read_string(void) { - size_t len = read_uint(); - if (!len) { - return std::string(); - } - char * buf = new char[len]; - gzread(file, buf, (unsigned)len); - std::string value(buf, len); - delete [] buf; -#if TRACE_VERBOSE - std::cerr << "\tSTRING \"" << value << "\"\n"; -#endif - return value; - } + void scan_arg(Call *call); - unsigned long long read_uint(void) { - unsigned long long value = 0; - int c; - unsigned shift = 0; - do { - c = gzgetc(file); - if (c == -1) { - break; - } - value |= (unsigned long long)(c & 0x7f) << shift; - shift += 7; - } while(c & 0x80); -#if TRACE_VERBOSE - std::cerr << "\tUINT " << value << "\n"; -#endif - return value; - } + void scan_value(void); - int read_byte(void) { - int c = gzgetc(file); -#if TRACE_VERBOSE - if (c < 0) - std::cerr << "\tEOF" << "\n"; - else - std::cerr << "\tBYTE 0x" << std::hex << c << std::dec << "\n"; -#endif - return c; - } -}; + void scan_sint(); + + void scan_uint(); + void scan_float(); -unsigned long long Trace::Parser::version = 0; + void scan_double(); + + void scan_string(); + + void scan_enum(); + + void scan_bitmask(); + + void scan_array(void); + + void scan_blob(void); + + void scan_struct(); + + void scan_opaque(); + + void skip_string(void); + + void skip_uint(void); + + inline void skip_byte(void); +}; } /* namespace Trace */