X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=trace_parser.cpp;h=d7b20d2c450faaab61cc986c6c046b72df5a4caa;hb=99f84fa0e278f4ca30577c22ede85c643c6017cc;hp=95dbec50d8da620e972d49663066f1277ccc5d73;hpb=2257168033b52be3094efdbd7eadff8eb77a4c4e;p=apitrace diff --git a/trace_parser.cpp b/trace_parser.cpp index 95dbec5..d7b20d2 100644 --- a/trace_parser.cpp +++ b/trace_parser.cpp @@ -98,22 +98,83 @@ void Parser::close(void) { } deleteAll(calls); - deleteAll(functions); - deleteAll(structs); - deleteAll(enums); - deleteAll(bitmasks); + + // Delete all signature data. Signatures are mere structures which don't + // own their own memory, so we need to destroy all data we created here. + + for (FunctionMap::iterator it = functions.begin(); it != functions.end(); ++it) { + FunctionSigState *sig = *it; + if (sig) { + delete [] sig->name; + for (unsigned arg = 0; arg < sig->num_args; ++arg) { + delete [] sig->arg_names[arg]; + } + delete [] sig->arg_names; + delete sig; + } + } + functions.clear(); + + for (StructMap::iterator it = structs.begin(); it != structs.end(); ++it) { + StructSigState *sig = *it; + if (sig) { + delete [] sig->name; + for (unsigned member = 0; member < sig->num_members; ++member) { + delete [] sig->member_names[member]; + } + delete [] sig->member_names; + delete sig; + } + } + structs.clear(); + + for (EnumMap::iterator it = enums.begin(); it != enums.end(); ++it) { + EnumSigState *sig = *it; + if (sig) { + delete [] sig->name; + delete sig; + } + } + enums.clear(); + + for (BitmaskMap::iterator it = bitmasks.begin(); it != bitmasks.end(); ++it) { + BitmaskSigState *sig = *it; + if (sig) { + for (unsigned flag = 0; flag < sig->num_flags; ++flag) { + delete [] sig->flags[flag].name; + } + delete [] sig->flags; + delete sig; + } + } + bitmasks.clear(); +} + + +void Parser::getBookmark(ParseBookmark &bookmark) { + bookmark.offset = file->currentOffset(); + bookmark.next_call_no = next_call_no; +} + + +void Parser::setBookmark(const ParseBookmark &bookmark) { + file->setCurrentOffset(bookmark.offset); + next_call_no = bookmark.next_call_no; + + // Simply ignore all pending calls + deleteAll(calls); } -Call *Parser::parse_call(void) { +Call *Parser::parse_call(Mode mode) { do { int c = read_byte(); switch(c) { case Trace::EVENT_ENTER: - parse_enter(); + parse_enter(mode); break; case Trace::EVENT_LEAVE: - return parse_leave(); + return parse_leave(mode); default: std::cerr << "error: unknown event " << c << "\n"; exit(1); @@ -142,42 +203,139 @@ T *lookup(std::vector &map, size_t index) { } -void Parser::parse_enter(void) { +FunctionSig *Parser::parse_function_sig(void) { size_t id = read_uint(); - FunctionSig *sig = lookup(functions, id); - const File::Offset offset = file->currentOffset(); - bool callWithSig = callWithSignature(offset); - if (!sig || callWithSig) { - if (!sig) { - sig = new FunctionSig; - sig->id = id; - sig->name = read_string(); - sig->num_args = read_uint(); - const char **arg_names = new const char *[sig->num_args]; - for (unsigned i = 0; i < sig->num_args; ++i) { - arg_names[i] = read_string(); - } - sig->arg_names = arg_names; - functions[id] = sig; - m_callSigOffsets.insert(offset); - } else { - /* skip over the signature */ - skip_string(); /* name */ - int num_args = read_uint(); - for (unsigned i = 0; i < num_args; ++i) { - skip_string(); /*arg_name*/ + FunctionSigState *sig = lookup(functions, id); + + if (!sig) { + /* parse the signature */ + sig = new FunctionSigState; + sig->id = id; + sig->name = read_string(); + sig->num_args = read_uint(); + const char **arg_names = new const char *[sig->num_args]; + for (unsigned i = 0; i < sig->num_args; ++i) { + arg_names[i] = read_string(); + } + sig->arg_names = arg_names; + sig->offset = file->currentOffset(); + functions[id] = sig; + } else if (file->currentOffset() < sig->offset) { + /* skip over the signature */ + skip_string(); /* name */ + int num_args = read_uint(); + for (unsigned i = 0; i < num_args; ++i) { + skip_string(); /*arg_name*/ + } + } + + assert(sig); + return sig; +} + + +StructSig *Parser::parse_struct_sig() { + size_t id = read_uint(); + + StructSigState *sig = lookup(structs, id); + + if (!sig) { + /* parse the signature */ + sig = new StructSigState; + sig->id = id; + sig->name = read_string(); + sig->num_members = read_uint(); + const char **member_names = new const char *[sig->num_members]; + for (unsigned i = 0; i < sig->num_members; ++i) { + member_names[i] = read_string(); + } + sig->member_names = member_names; + sig->offset = file->currentOffset(); + structs[id] = sig; + } else if (file->currentOffset() < sig->offset) { + /* skip over the signature */ + skip_string(); /* name */ + unsigned num_members = read_uint(); + for (unsigned i = 0; i < num_members; ++i) { + skip_string(); /* member_name */ + } + } + + assert(sig); + return sig; +} + + +EnumSig *Parser::parse_enum_sig() { + size_t id = read_uint(); + + EnumSigState *sig = lookup(enums, id); + + if (!sig) { + /* parse the signature */ + sig = new EnumSigState; + sig->id = id; + sig->name = read_string(); + Value *value = parse_value(); + sig->value = value->toSInt(); + delete value; + sig->offset = file->currentOffset(); + enums[id] = sig; + } else if (file->currentOffset() < sig->offset) { + /* skip over the signature */ + skip_string(); /*name*/ + scan_value(); + } + + assert(sig); + return sig; +} + + +BitmaskSig *Parser::parse_bitmask_sig() { + size_t id = read_uint(); + + BitmaskSigState *sig = lookup(bitmasks, id); + + if (!sig) { + /* parse the signature */ + sig = new BitmaskSigState; + sig->id = id; + sig->num_flags = read_uint(); + BitmaskFlag *flags = new BitmaskFlag[sig->num_flags]; + for (BitmaskFlag *it = flags; it != flags + sig->num_flags; ++it) { + it->name = read_string(); + it->value = read_uint(); + if (it->value == 0 && it != flags) { + std::cerr << "warning: bitmask " << it->name << " is zero but is not first flag\n"; } } + sig->flags = flags; + sig->offset = file->currentOffset(); + bitmasks[id] = sig; + } else if (file->currentOffset() < sig->offset) { + /* skip over the signature */ + int num_flags = read_uint(); + for (int i = 0; i < num_flags; ++i) { + skip_string(); /*name */ + skip_uint(); /* value */ + } } + assert(sig); + return sig; +} - Call *call = new Call(sig); +void Parser::parse_enter(Mode mode) { + FunctionSig *sig = parse_function_sig(); + + Call *call = new Call(sig); call->no = next_call_no++; - if (parse_call_details(call)) { + if (parse_call_details(call, mode)) { calls.push_back(call); } else { delete call; @@ -185,7 +343,7 @@ void Parser::parse_enter(void) { } -Call *Parser::parse_leave(void) { +Call *Parser::parse_leave(Mode mode) { unsigned call_no = read_uint(); Call *call = NULL; for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) { @@ -199,7 +357,7 @@ Call *Parser::parse_leave(void) { return NULL; } - if (parse_call_details(call)) { + if (parse_call_details(call, mode)) { return call; } else { delete call; @@ -208,17 +366,17 @@ Call *Parser::parse_leave(void) { } -bool Parser::parse_call_details(Call *call) { +bool Parser::parse_call_details(Call *call, Mode mode) { do { int c = read_byte(); switch(c) { case Trace::CALL_END: return true; case Trace::CALL_ARG: - parse_arg(call); + parse_arg(call, mode); break; case Trace::CALL_RET: - call->ret = parse_value(); + call->ret = parse_value(mode); break; default: std::cerr << "error: ("<name()<< ") unknown call detail " @@ -231,13 +389,15 @@ bool Parser::parse_call_details(Call *call) { } -void Parser::parse_arg(Call *call) { +void Parser::parse_arg(Call *call, Mode mode) { unsigned index = read_uint(); - Value *value = parse_value(); - if (index >= call->args.size()) { - call->args.resize(index + 1); + Value *value = parse_value(mode); + if (value) { + if (index >= call->args.size()) { + call->args.resize(index + 1); + } + call->args[index] = value; } - call->args[index] = value; } @@ -304,331 +464,6 @@ Value *Parser::parse_value(void) { } -Value *Parser::parse_sint() { - return new SInt(-(signed long long)read_uint()); -} - - -Value *Parser::parse_uint() { - return new UInt(read_uint()); -} - - -Value *Parser::parse_float() { - float value; - file->read(&value, sizeof value); - return new Float(value); -} - - -Value *Parser::parse_double() { - double value; - file->read(&value, sizeof value); - return new Float(value); -} - - -Value *Parser::parse_string() { - return new String(read_string()); -} - - -Value *Parser::parse_enum() { - size_t id = read_uint(); - EnumSig *sig = lookup(enums, id); - const File::Offset offset = file->currentOffset(); - bool enumWithSig = enumWithSignature(offset); - if (!sig || enumWithSig) { - if (!sig) { - sig = new EnumSig; - sig->id = id; - sig->name = read_string(); - Value *value = parse_value(); - sig->value = value->toSInt(); - delete value; - enums[id] = sig; - m_enumSigOffsets.insert(offset); - } else { - skip_string(); /*name*/ - scan_value(); - } - } - assert(sig); - return new Enum(sig); -} - - -Value *Parser::parse_bitmask() { - size_t id = read_uint(); - BitmaskSig *sig = lookup(bitmasks, id); - const File::Offset offset = file->currentOffset(); - bool bitmaskWithSig = bitmaskWithSignature(offset); - if (!sig || bitmaskWithSig) { - if (!sig) { - sig = new BitmaskSig; - sig->id = id; - sig->num_flags = read_uint(); - BitmaskFlag *flags = new BitmaskFlag[sig->num_flags]; - for (BitmaskFlag *it = flags; it != flags + sig->num_flags; ++it) { - it->name = read_string(); - it->value = read_uint(); - if (it->value == 0 && it != flags) { - std::cerr << "warning: bitmask " << it->name << " is zero but is not first flag\n"; - } - } - sig->flags = flags; - bitmasks[id] = sig; - m_bitmaskSigOffsets.insert(offset); - } else { - int num_flags = read_uint(); - for (int i = 0; i < num_flags; ++i) { - skip_string(); /*name */ - skip_uint(); /* value */ - } - } - } - assert(sig); - - unsigned long long value = read_uint(); - - return new Bitmask(sig, value); -} - - -Value *Parser::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 *Parser::parse_blob(void) { - size_t size = read_uint(); - Blob *blob = new Blob(size); - if (size) { - file->read(blob->buf, (unsigned)size); - } - return blob; -} - - -Value *Parser::parse_struct() { - size_t id = read_uint(); - - StructSig *sig = lookup(structs, id); - const File::Offset offset = file->currentOffset(); - bool structWithSig = structWithSignature(offset); - if (!sig || structWithSig) { - if (!sig) { - sig = new StructSig; - sig->id = id; - sig->name = read_string(); - sig->num_members = read_uint(); - const char **member_names = new const char *[sig->num_members]; - for (unsigned i = 0; i < sig->num_members; ++i) { - member_names[i] = read_string(); - } - sig->member_names = member_names; - structs[id] = sig; - m_structSigOffsets.insert(offset); - } else { - skip_string(); /* name */ - unsigned num_members = read_uint(); - for (unsigned i = 0; i < num_members; ++i) { - skip_string(); /* member_name */ - } - } - } - assert(sig); - - Struct *value = new Struct(sig); - - for (size_t i = 0; i < sig->num_members; ++i) { - value->members[i] = parse_value(); - } - - return value; -} - - -Value *Parser::parse_opaque() { - unsigned long long addr; - addr = read_uint(); - return new Pointer(addr); -} - - -const char * Parser::read_string(void) { - size_t len = read_uint(); - char * value = new char[len + 1]; - if (len) { - file->read(value, (unsigned)len); - } - value[len] = 0; -#if TRACE_VERBOSE - std::cerr << "\tSTRING \"" << value << "\"\n"; -#endif - return value; -} - - -unsigned long long Parser::read_uint(void) { - unsigned long long value = 0; - int c; - unsigned shift = 0; - do { - c = file->getc(); - 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; -} - - -inline int Parser::read_byte(void) { - int c = file->getc(); -#if TRACE_VERBOSE - if (c < 0) - std::cerr << "\tEOF" << "\n"; - else - std::cerr << "\tBYTE 0x" << std::hex << c << std::dec << "\n"; -#endif - return c; -} - - -inline bool Parser::callWithSignature(const File::Offset &offset) const -{ - return m_callSigOffsets.find(offset) != m_callSigOffsets.end(); -} - -inline bool Parser::structWithSignature(const File::Offset &offset) const -{ - return m_structSigOffsets.find(offset) != m_structSigOffsets.end(); -} - -inline bool Parser::enumWithSignature(const File::Offset &offset) const -{ - return m_enumSigOffsets.find(offset) != m_enumSigOffsets.end(); -} - -inline bool Parser::bitmaskWithSignature(const File::Offset &offset) const -{ - return m_bitmaskSigOffsets.find(offset) != m_bitmaskSigOffsets.end(); -} - -Call * Parser::scan_call() -{ - do { - int c = read_byte(); - switch(c) { - case Trace::EVENT_ENTER: - scan_enter(); - break; - case Trace::EVENT_LEAVE: - return scan_leave(); - default: - std::cerr << "error: unknown event " << c << "\n"; - exit(1); - case -1: - for (CallList::iterator it = calls.begin(); it != calls.end(); ++it) { - std::cerr << "warning: incomplete call " << (*it)->name() << "\n"; - std::cerr << **it << "\n"; - } - return NULL; - } - } while (true); -} - -void Parser::scan_enter(void) { - size_t id = read_uint(); - - FunctionSig *sig = lookup(functions, id); - const File::Offset offset = file->currentOffset(); - if (!sig) { - sig = new FunctionSig; - sig->id = id; - sig->name = read_string(); - sig->num_args = read_uint(); - const char **arg_names = new const char *[sig->num_args]; - for (unsigned i = 0; i < sig->num_args; ++i) { - arg_names[i] = read_string(); - } - sig->arg_names = arg_names; - functions[id] = sig; - m_callSigOffsets.insert(offset); - } - assert(sig); - - Call *call = new Call(sig); - call->no = next_call_no++; - - if (scan_call_details(call)) { - calls.push_back(call); - } else { - delete call; - } -} - -Call *Parser::scan_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; - } - } - if (!call) { - return NULL; - } - - if (scan_call_details(call)) { - return call; - } else { - delete call; - return NULL; - } -} - -bool Parser::scan_call_details(Call *call) { - do { - int c = read_byte(); - switch(c) { - case Trace::CALL_END: - return true; - case Trace::CALL_ARG: - scan_arg(call); - break; - case Trace::CALL_RET: - scan_value(); - break; - default: - std::cerr << "error: ("<name()<< ") unknown call detail " - << c << "\n"; - exit(1); - case -1: - return false; - } - } while(true); -} - -void Parser::scan_arg(Call *call) { - skip_uint(); /* index */ - scan_value(); /* value */ -} - - void Parser::scan_value(void) { int c = read_byte(); switch(c) { @@ -678,75 +513,96 @@ void Parser::scan_value(void) { } +Value *Parser::parse_sint() { + return new SInt(-(signed long long)read_uint()); +} + + void Parser::scan_sint() { skip_uint(); } +Value *Parser::parse_uint() { + return new UInt(read_uint()); +} + + void Parser::scan_uint() { skip_uint(); } +Value *Parser::parse_float() { + float value; + file->read(&value, sizeof value); + return new Float(value); +} + + void Parser::scan_float() { file->skip(sizeof(float)); } +Value *Parser::parse_double() { + double value; + file->read(&value, sizeof value); + return new Float(value); +} + + void Parser::scan_double() { file->skip(sizeof(double)); } +Value *Parser::parse_string() { + return new String(read_string()); +} + + void Parser::scan_string() { skip_string(); } +Value *Parser::parse_enum() { + EnumSig *sig = parse_enum_sig(); + return new Enum(sig); +} + + void Parser::scan_enum() { - size_t id = read_uint(); - EnumSig *sig = lookup(enums, id); - const File::Offset offset = file->currentOffset(); - if (!sig) { - sig = new EnumSig; - sig->id = id; - sig->name = read_string(); - Value *value = parse_value(); - sig->value = value->toSInt(); - delete value; - enums[id] = sig; - m_enumSigOffsets.insert(offset); - } - assert(sig); + parse_enum_sig(); } -void Parser::scan_bitmask() { - size_t id = read_uint(); - BitmaskSig *sig = lookup(bitmasks, id); - const File::Offset offset = file->currentOffset(); - if (!sig) { - sig = new BitmaskSig; - sig->id = id; - sig->num_flags = read_uint(); - BitmaskFlag *flags = new BitmaskFlag[sig->num_flags]; - for (BitmaskFlag *it = flags; it != flags + sig->num_flags; ++it) { - it->name = read_string(); - it->value = read_uint(); - if (it->value == 0 && it != flags) { - std::cerr << "warning: bitmask " << it->name << " is zero but is not first flag\n"; - } - } - sig->flags = flags; - bitmasks[id] = sig; - m_bitmaskSigOffsets.insert(offset); - } - assert(sig); +Value *Parser::parse_bitmask() { + BitmaskSig *sig = parse_bitmask_sig(); + unsigned long long value = read_uint(); + + return new Bitmask(sig, value); +} + + +void Parser::scan_bitmask() { + parse_bitmask_sig(); skip_uint(); /* value */ } +Value *Parser::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; +} + + void Parser::scan_array(void) { size_t len = read_uint(); for (size_t i = 0; i < len; ++i) { @@ -755,48 +611,92 @@ void Parser::scan_array(void) { } +Value *Parser::parse_blob(void) { + size_t size = read_uint(); + Blob *blob = new Blob(size); + if (size) { + file->read(blob->buf, (unsigned)size); + } + return blob; +} + + void Parser::scan_blob(void) { size_t size = read_uint(); if (size) { - file->skip((unsigned)size); + file->skip(size); } } -void Parser::scan_struct() { - size_t id = read_uint(); +Value *Parser::parse_struct() { + StructSig *sig = parse_struct_sig(); + Struct *value = new Struct(sig); - StructSig *sig = lookup(structs, id); - const File::Offset offset = file->currentOffset(); - if (!sig) { - sig = new StructSig; - sig->id = id; - sig->name = read_string(); - sig->num_members = read_uint(); - const char **member_names = new const char *[sig->num_members]; - for (unsigned i = 0; i < sig->num_members; ++i) { - member_names[i] = read_string(); - } - sig->member_names = member_names; - structs[id] = sig; - m_structSigOffsets.insert(offset); + for (size_t i = 0; i < sig->num_members; ++i) { + value->members[i] = parse_value(); } - assert(sig); + return value; +} + + +void Parser::scan_struct() { + StructSig *sig = parse_struct_sig(); for (size_t i = 0; i < sig->num_members; ++i) { scan_value(); } } +Value *Parser::parse_opaque() { + unsigned long long addr; + addr = read_uint(); + return new Pointer(addr); +} + + void Parser::scan_opaque() { skip_uint(); } +const char * Parser::read_string(void) { + size_t len = read_uint(); + char * value = new char[len + 1]; + if (len) { + file->read(value, (unsigned)len); + } + value[len] = 0; +#if TRACE_VERBOSE + std::cerr << "\tSTRING \"" << value << "\"\n"; +#endif + return value; +} + + void Parser::skip_string(void) { size_t len = read_uint(); - file->skip((unsigned)len); + file->skip(len); +} + + +unsigned long long Parser::read_uint(void) { + unsigned long long value = 0; + int c; + unsigned shift = 0; + do { + c = file->getc(); + 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; } @@ -811,6 +711,18 @@ void Parser::skip_uint(void) { } +inline int Parser::read_byte(void) { + int c = file->getc(); +#if TRACE_VERBOSE + if (c < 0) + std::cerr << "\tEOF" << "\n"; + else + std::cerr << "\tBYTE 0x" << std::hex << c << std::dec << "\n"; +#endif + return c; +} + + inline void Parser::skip_byte(void) { file->skip(1); }