From 34a407d4a95830ff9fad05e2bff34dcfc631c931 Mon Sep 17 00:00:00 2001 From: Matteo Martincigh Date: Wed, 6 Nov 2019 15:30:54 +0000 Subject: IVGCVSW-4072 Add stream header to Timeline Message Directory packet * Refactored the WriteTimelineMessageDirectoryPacket function * Added the stream header to the packet * Updated decoders/parsers * Updated unit tests accordingly * Minor refactoring Signed-off-by: Matteo Martincigh Change-Id: I58f15fde54adc6414ca9fd5fb8d6157cad867339 --- src/profiling/ProfilingUtils.cpp | 213 +++++++++++++++++++++++---------------- 1 file changed, 124 insertions(+), 89 deletions(-) (limited to 'src/profiling/ProfilingUtils.cpp') diff --git a/src/profiling/ProfilingUtils.cpp b/src/profiling/ProfilingUtils.cpp index 4dde235ecc..8a7d9147cc 100644 --- a/src/profiling/ProfilingUtils.cpp +++ b/src/profiling/ProfilingUtils.cpp @@ -134,6 +134,13 @@ void WriteUint16(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint WriteUint16(packetBuffer->GetWritableData(), offset, value); } +void WriteUint8(const IPacketBufferPtr& packetBuffer, unsigned int offset, uint8_t value) +{ + BOOST_ASSERT(packetBuffer); + + WriteUint8(packetBuffer->GetWritableData(), offset, value); +} + void WriteBytes(unsigned char* buffer, unsigned int offset, const void* value, unsigned int valueSize) { BOOST_ASSERT(buffer); @@ -177,6 +184,13 @@ void WriteUint16(unsigned char* buffer, unsigned int offset, uint16_t value) buffer[offset + 1] = static_cast((value >> 8) & 0xFF); } +void WriteUint8(unsigned char* buffer, unsigned int offset, uint8_t value) +{ + BOOST_ASSERT(buffer); + + buffer[offset] = static_cast(value); +} + void ReadBytes(const IPacketBufferPtr& packetBuffer, unsigned int offset, unsigned int valueSize, uint8_t outValue[]) { BOOST_ASSERT(packetBuffer); @@ -294,46 +308,6 @@ std::string GetProcessName() return name; } -/// Creates a timeline packet header -/// -/// \params -/// packetFamiliy Timeline Packet Family -/// packetClass Timeline Packet Class -/// packetType Timeline Packet Type -/// streamId Stream identifier -/// seqeunceNumbered When non-zero the 4 bytes following the header is a u32 sequence number -/// dataLength Unsigned 24-bit integer. Length of data, in bytes. Zero is permitted -/// -/// \returns -/// Pair of uint32_t containing word0 and word1 of the header -std::pair CreateTimelinePacketHeader(uint32_t packetFamily, - uint32_t packetClass, - uint32_t packetType, - uint32_t streamId, - uint32_t sequenceNumbered, - uint32_t dataLength) -{ - // Packet header word 0: - // 26:31 [6] packet_family: timeline Packet Family, value 0b000001 - // 19:25 [7] packet_class: packet class - // 16:18 [3] packet_type: packet type - // 8:15 [8] reserved: all zeros - // 0:7 [8] stream_id: stream identifier - uint32_t packetHeaderWord0 = ((packetFamily & 0x0000003F) << 26) | - ((packetClass & 0x0000007F) << 19) | - ((packetType & 0x00000007) << 16) | - ((streamId & 0x00000007) << 0); - - // Packet header word 1: - // 25:31 [7] reserved: all zeros - // 24 [1] sequence_numbered: when non-zero the 4 bytes following the header is a u32 sequence number - // 0:23 [24] data_length: unsigned 24-bit integer. Length of data, in bytes. Zero is permitted - uint32_t packetHeaderWord1 = ((sequenceNumbered & 0x00000001) << 24) | - ((dataLength & 0x00FFFFFF) << 0); - - return std::make_pair(packetHeaderWord0, packetHeaderWord1); -} - // Calculate the actual length an SwString will be including the terminating null character // padding to bring it to the next uint32_t boundary but minus the leading uint32_t encoding // the size to allow the offset to be correctly updated when decoding a binary packet. @@ -357,7 +331,7 @@ SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer, unsigned in // Read the decl_id uint32_t readDeclId = ReadUint32(packetBuffer, offset); - swTraceMessage.id = readDeclId; + swTraceMessage.m_Id = readDeclId; // SWTrace "namestring" format // length of the string (first 4 bytes) + string + null terminator @@ -371,10 +345,10 @@ SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer, unsigned in std::memcpy(swTraceStringBuffer.data(), packetBuffer + offset, swTraceStringBuffer.size()); - swTraceMessage.name.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // name + swTraceMessage.m_Name.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // name // Check the ui_name - offset += CalculateSizeOfPaddedSwString(swTraceMessage.name); + offset += CalculateSizeOfPaddedSwString(swTraceMessage.m_Name); uint32_t swTraceUINameLength = ReadUint32(packetBuffer, offset); offset += uint32_t_size; @@ -382,10 +356,10 @@ SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer, unsigned in std::memcpy(swTraceStringBuffer.data(), packetBuffer + offset, swTraceStringBuffer.size()); - swTraceMessage.uiName.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // ui_name + swTraceMessage.m_UiName.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // ui_name // Check arg_types - offset += CalculateSizeOfPaddedSwString(swTraceMessage.uiName); + offset += CalculateSizeOfPaddedSwString(swTraceMessage.m_UiName); uint32_t swTraceArgTypesLength = ReadUint32(packetBuffer, offset); offset += uint32_t_size; @@ -393,7 +367,7 @@ SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer, unsigned in std::memcpy(swTraceStringBuffer.data(), packetBuffer + offset, swTraceStringBuffer.size()); - swTraceMessage.argTypes.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // arg_types + swTraceMessage.m_ArgTypes.assign(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); // arg_types std::string swTraceString(swTraceStringBuffer.begin(), swTraceStringBuffer.end()); @@ -411,7 +385,7 @@ SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer, unsigned in std::string argName; while (std::getline(stringStream, argName, ',')) { - swTraceMessage.argNames.push_back(argName); + swTraceMessage.m_ArgNames.push_back(argName); } offset += CalculateSizeOfPaddedSwString(swTraceString); @@ -419,6 +393,46 @@ SwTraceMessage ReadSwTraceMessage(const unsigned char* packetBuffer, unsigned in return swTraceMessage; } +/// Creates a timeline packet header +/// +/// \params +/// packetFamiliy Timeline Packet Family +/// packetClass Timeline Packet Class +/// packetType Timeline Packet Type +/// streamId Stream identifier +/// seqeunceNumbered When non-zero the 4 bytes following the header is a u32 sequence number +/// dataLength Unsigned 24-bit integer. Length of data, in bytes. Zero is permitted +/// +/// \returns +/// Pair of uint32_t containing word0 and word1 of the header +std::pair CreateTimelinePacketHeader(uint32_t packetFamily, + uint32_t packetClass, + uint32_t packetType, + uint32_t streamId, + uint32_t sequenceNumbered, + uint32_t dataLength) +{ + // Packet header word 0: + // 26:31 [6] packet_family: timeline Packet Family, value 0b000001 + // 19:25 [7] packet_class: packet class + // 16:18 [3] packet_type: packet type + // 8:15 [8] reserved: all zeros + // 0:7 [8] stream_id: stream identifier + uint32_t packetHeaderWord0 = ((packetFamily & 0x0000003F) << 26) | + ((packetClass & 0x0000007F) << 19) | + ((packetType & 0x00000007) << 16) | + ((streamId & 0x00000007) << 0); + + // Packet header word 1: + // 25:31 [7] reserved: all zeros + // 24 [1] sequence_numbered: when non-zero the 4 bytes following the header is a u32 sequence number + // 0:23 [24] data_length: unsigned 24-bit integer. Length of data, in bytes. Zero is permitted + uint32_t packetHeaderWord1 = ((sequenceNumbered & 0x00000001) << 24) | + ((dataLength & 0x00FFFFFF) << 0); + + return std::make_pair(packetHeaderWord0, packetHeaderWord1); +} + /// Creates a packet header for the timeline messages: /// * declareLabel /// * declareEntity @@ -675,11 +689,15 @@ TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer, } // Utils + unsigned int uint8_t_size = sizeof(uint8_t); unsigned int uint32_t_size = sizeof(uint32_t); + unsigned int uint64_t_size = sizeof(uint64_t); + unsigned int threadId_size = sizeof(std::thread::id); // The payload/data of the packet consists of swtrace event definitions encoded according // to the swtrace directory specification. The messages being the five defined below: - // | decl_id | decl_name | ui_name | arg_types | arg_names | + // + // | decl_id | decl_name | ui_name | arg_types | arg_names | // |-----------|---------------------|-----------------------|-------------|-------------------------------------| // | 0 | declareLabel | declare label | ps | guid,value | // | 1 | declareEntity | declare entity | p | guid | @@ -687,42 +705,50 @@ TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer, // | 3 | declareRelationship | declare relationship | Ippp | relationshipType,relationshipGuid, | // | | | | | headGuid,tailGuid | // | 4 | declareEvent | declare event | @tp | timestamp,threadId,eventGuid | - std::vector> timelineDirectoryMessages { - {"declareLabel", "declare label", "ps", "guid,value"}, - {"declareEntity", "declare entity", "p", "guid"}, - {"declareEventClass", "declare event class", "p", "guid"}, - {"declareRelationship", "declare relationship", "Ippp", "relationshipType,relationshipGuid,headGuid,tailGuid"}, - {"declareEvent", "declare event", "@tp", "timestamp,threadId,eventGuid"} + { "0", "declareLabel", "declare label", "ps", "guid,value" }, + { "1", "declareEntity", "declare entity", "p", "guid" }, + { "2", "declareEventClass", "declare event class", "p", "guid" }, + { "3", "declareRelationship", "declare relationship", "Ippp", + "relationshipType,relationshipGuid,headGuid,tailGuid" }, + { "4", "declareEvent", "declare event", "@tp", "timestamp,threadId,eventGuid" } }; - unsigned int messagesDataLength = 0u; - std::vector>> swTraceTimelineDirectoryMessages; - - for (const auto& timelineDirectoryMessage : timelineDirectoryMessages) + // Build the message declarations + std::vector swTraceBuffer; + for (const auto& directoryComponent : timelineDirectoryMessages) { - messagesDataLength += uint32_t_size; // decl_id - - std::vector> swTraceStringsVector; - for (const auto& label : timelineDirectoryMessage) + // decl_id + uint32_t declId = 0; + try + { + declId = boost::numeric_cast(std::stoul(directoryComponent[0])); + } + catch (const std::exception&) { - std::vector swTraceString; - bool result = StringToSwTraceString(label, swTraceString); - if (!result) - { - return TimelinePacketStatus::Error; - } - - messagesDataLength += boost::numeric_cast(swTraceString.size()) * uint32_t_size; - swTraceStringsVector.push_back(swTraceString); + return TimelinePacketStatus::Error; + } + swTraceBuffer.push_back(declId); + + bool result = true; + result &= ConvertDirectoryComponent(directoryComponent[1], swTraceBuffer); // decl_name + result &= ConvertDirectoryComponent (directoryComponent[2], swTraceBuffer); // ui_name + result &= ConvertDirectoryComponent(directoryComponent[3], swTraceBuffer); // arg_types + result &= ConvertDirectoryComponent (directoryComponent[4], swTraceBuffer); // arg_names + if (!result) + { + return TimelinePacketStatus::Error; } - swTraceTimelineDirectoryMessages.push_back(swTraceStringsVector); } + unsigned int dataLength = 3 * uint8_t_size + // Stream header (3 bytes) + boost::numeric_cast(swTraceBuffer.size()) * + uint32_t_size; // Trace directory (5 messages) + // Calculate the timeline directory binary packet size (in bytes) unsigned int timelineDirectoryPacketSize = 2 * uint32_t_size + // Header (2 words) - messagesDataLength; // 5 messages length + dataLength; // Payload // Check whether the timeline directory binary packet fits in the given buffer if (timelineDirectoryPacketSize > bufferSize) @@ -731,8 +757,7 @@ TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer, } // Create packet header - uint32_t dataLength = boost::numeric_cast(messagesDataLength); - std::pair packetHeader = CreateTimelinePacketHeader(1, 0, 0, 0, 0, dataLength); + auto packetHeader = CreateTimelinePacketHeader(1, 0, 0, 0, 0, boost::numeric_cast(dataLength)); // Initialize the offset for writing in the buffer unsigned int offset = 0; @@ -743,23 +768,33 @@ TimelinePacketStatus WriteTimelineMessageDirectoryPackage(unsigned char* buffer, WriteUint32(buffer, offset, packetHeader.second); offset += uint32_t_size; - WriteUint32(buffer, offset, static_cast(swTraceTimelineDirectoryMessages.size())); + // Write the stream header + uint8_t streamVersion = 4; + uint8_t pointerBytes = boost::numeric_cast(uint64_t_size); // All GUIDs are uint64_t + uint8_t threadIdBytes = boost::numeric_cast(threadId_size); + switch (threadIdBytes) + { + case 4: // Typically Windows and Android + case 8: // Typically Linux + break; // Valid values + default: + return TimelinePacketStatus::Error; // Invalid value + } + WriteUint8(buffer, offset, streamVersion); + offset += uint8_t_size; + WriteUint8(buffer, offset, pointerBytes); + offset += uint8_t_size; + WriteUint8(buffer, offset, threadIdBytes); + offset += uint8_t_size; + + // Write the SWTrace directory + uint32_t numberOfDeclarations = boost::numeric_cast(timelineDirectoryMessages.size()); + WriteUint32(buffer, offset, numberOfDeclarations); // Number of declarations offset += uint32_t_size; - - for (unsigned int i = 0u; i < swTraceTimelineDirectoryMessages.size(); ++i) + for (uint32_t i : swTraceBuffer) { - // Write the timeline binary packet payload to the buffer - WriteUint32(buffer, offset, i); // decl_id + WriteUint32(buffer, offset, i); // Message declarations offset += uint32_t_size; - - for (std::vector swTraceString : swTraceTimelineDirectoryMessages[i]) - { - for (uint32_t swTraceDeclStringWord : swTraceString) - { - WriteUint32(buffer, offset, swTraceDeclStringWord); - offset += uint32_t_size; - } - } } // Update the number of bytes written -- cgit v1.2.1