Ejemplo n.º 1
0
 public CtfTrace(CtfPropertyBag bag)
 {
     Major     = bag.GetShort("major");
     Minor     = bag.GetShort("minor");
     UUID      = new Guid(bag.GetString("uuid"));
     ByteOrder = bag.GetString("byte_order");
     Header    = bag.GetStruct("packet.header");
 }
Ejemplo n.º 2
0
        public void ReadStruct(CtfStruct strct)
        {
            var fields = strct.Fields;

            for (int i = 0; i < fields.Length; i++)
            {
                ReadTypeIntoBuffer(strct, fields[i].Type);
            }
        }
Ejemplo n.º 3
0
        private object ReadType(CtfStruct strct, object[] result, CtfMetadataType type)
        {
            Align(type.Align);

            switch (type.CtfType)
            {
            case CtfTypes.Array:
                CtfArray array = (CtfArray)type;
                int      len   = array.GetLength(strct, result);

                object[] ret = new object[len];

                for (int j = 0; j < len; j++)
                {
                    ret[j] = ReadType(null, null, array.Type);
                }

                return(ret);

            case CtfTypes.Enum:
                return(ReadType(strct, result, ((CtfEnum)type).Type));

            case CtfTypes.Float:
                CtfFloat flt = (CtfFloat)type;
                ReadBits(flt.Exp + flt.Mant);
                return(0f);     // TODO:  Not implemented.

            case CtfTypes.Integer:
                CtfInteger ctfInt = (CtfInteger)type;
                return(ReadInteger(ctfInt));

            case CtfTypes.String:
                bool ascii = ((CtfString)type).IsAscii;
                return(ReadString(ascii));

            case CtfTypes.Struct:
                return(ReadStruct((CtfStruct)type));

            case CtfTypes.Variant:
                CtfVariant var = (CtfVariant)type;

                int      i        = strct.GetFieldIndex(var.Switch);
                CtfField field    = strct.Fields[i];
                CtfEnum  enumType = (CtfEnum)field.Type;

                int    value = strct.GetFieldValue <int>(result, i);
                string name  = enumType.GetName(value);

                field = var.Union.Where(f => f.Name == name).Single();
                return(ReadType(strct, result, field.Type));

            default:
                throw new InvalidOperationException();
            }
        }
Ejemplo n.º 4
0
        public int GetLength(CtfStruct strct, object[] values)
        {
            int len;

            if (int.TryParse(Index, out len))
            {
                return(len);
            }

            return(strct.GetFieldValue <int>(values, Index));
        }
Ejemplo n.º 5
0
        public object[] ReadStruct(CtfStruct strct)
        {
            var fields = strct.Fields;

            object[] result = new object[fields.Length];

            for (int i = 0; i < fields.Length; i++)
            {
                result[i] = ReadType(strct, result, fields[i].Type);
            }

            return(result);
        }
Ejemplo n.º 6
0
        private bool ReadTraceHeader()
        {
            // Read Trace Header
            CtfStruct traceHeader = _metadata.Trace.Header;

            int traceHeaderSize = traceHeader.GetSize();

            if (traceHeaderSize == CtfEvent.SizeIndeterminate)
            {
                throw new FormatException("Unexpected metadata format.");
            }

            int magicOffset = traceHeader.GetFieldOffset("magic");

            if (magicOffset < 0)
            {
                throw new FormatException("Unexpected metadata format: No magic field.");
            }

            int streamIdOffset = traceHeader.GetFieldOffset("stream_id");

            if (streamIdOffset < 0)
            {
                throw new FormatException("Unexpected metadata format: No stream_id field.");
            }

            // Convert to bytes instead of bits
            magicOffset     /= 8;
            streamIdOffset  /= 8;
            traceHeaderSize /= 8;

            if (_stream.Read(_buffer, 0, traceHeaderSize) != traceHeaderSize)
            {
                return(false);
            }

#if DEBUG
            _fileOffset += traceHeaderSize;
#endif

            uint magic = BitConverter.ToUInt32(_buffer, magicOffset);
            if (magic != 0xc1fc1fc1)
            {
                throw new FormatException("Unknown magic number in trace header.");
            }

            uint streamId = BitConverter.ToUInt32(_buffer, streamIdOffset);
            _ctfStream = _metadata.Streams[streamId];

            return(true);
        }
Ejemplo n.º 7
0
        private bool ReadPacketContext()
        {
            // Read Packet Context
            CtfStruct packetContext     = _ctfStream.PacketContext;
            int       packetContextSize = packetContext.GetSize();

            if (packetContextSize == CtfEvent.SizeIndeterminate)
            {
                throw new FormatException("Unexpected metadata format.");
            }

            int contentSizeOffset = packetContext.GetFieldOffset("content_size");

            if (contentSizeOffset < 0)
            {
                throw new FormatException("Unexpected metadata format: No context_size field.");
            }

            int packetSizeOffset = packetContext.GetFieldOffset("packet_size");

            if (packetSizeOffset < 0)
            {
                throw new FormatException("Unexpected metadata format: No packet_size field.");
            }

            // Convert to bytes instead of bits
            packetContextSize /= 8;
            contentSizeOffset /= 8;
            packetSizeOffset  /= 8;

            if (_stream.Read(_buffer, 0, packetContextSize) != packetContextSize)
            {
                return(false);
            }

#if DEBUG
            _fileOffset += packetContextSize;
#endif

            int headerSize = (_metadata.Trace.Header.GetSize() / 8) + packetContextSize;
            _contentSize = (long)BitConverter.ToUInt64(_buffer, contentSizeOffset) / 8 - headerSize;
            _packetSize  = (long)BitConverter.ToUInt64(_buffer, packetSizeOffset) / 8 - headerSize;

            return(true);
        }
Ejemplo n.º 8
0
        public IEnumerable <CtfEventHeader> EnumerateEventHeaders()
        {
            CtfStruct  header            = _streamDefinition.EventHeader;
            CtfEnum    id                = (CtfEnum)header.GetField("id").Type;
            CtfVariant v                 = (CtfVariant)header.GetField("v").Type;
            CtfStruct  extended          = (CtfStruct)v.GetVariant("extended").Type;
            CtfInteger extendedId        = (CtfInteger)extended.GetField("id").Type;
            CtfInteger extendedTimestamp = (CtfInteger)extended.GetField("timestamp").Type;
            CtfInteger compactTimestamp  = (CtfInteger)((CtfStruct)v.GetVariant("compact").Type).GetField("timestamp").Type;

            CtfInteger pid             = null;
            CtfInteger tid             = null;
            CtfArray   processName     = null;
            string     lastProcessName = "";
            int        processLen      = 0;
            CtfStruct  eventContext    = _streamDefinition.EventContext;

            if (eventContext != null)
            {
                pid         = (CtfInteger)eventContext.GetField("_vpid")?.Type;
                tid         = (CtfInteger)eventContext.GetField("_vtid")?.Type;
                processName = (CtfArray)eventContext.GetField("_procname")?.Type;

                // We only handle ascii process names, which seems to be the only thing lttng provides.
                if (processName != null)
                {
                    processLen = int.Parse(processName.Index);
                    Debug.Assert(processName.Type.GetSize() == 8);

                    if (processName.Type.GetSize() != 8)
                    {
                        processName = null;
                    }
                }
            }


            uint extendedIdValue = (uint)id.GetValue("extended").End;

            ulong lowMask = 0, highMask = 0, overflowBit = 0;
            ulong lastTimestamp = 0;

            while (!_eof)
            {
                if (_readHeader)
                {
                    throw new InvalidOperationException("Must read an events data before reading the header again.");
                }

                _header.Clear();
                ResetBuffer();
                ReadStruct(header);
                if (_eof)
                {
                    break;
                }

                ulong timestamp;
                uint  event_id = CtfInteger.ReadInt <uint>(id.Type, _buffer, id.BitOffset);

                if (event_id == extendedIdValue)
                {
                    event_id  = CtfInteger.ReadInt <uint>(extendedId, _buffer, extendedId.BitOffset);
                    timestamp = CtfInteger.ReadInt <ulong>(extendedTimestamp, _buffer, extendedTimestamp.BitOffset);
                }
                else
                {
                    if (overflowBit == 0)
                    {
                        overflowBit = (1ul << compactTimestamp.Size);
                        lowMask     = overflowBit - 1;
                        highMask    = ~lowMask;
                    }

                    ulong uint27timestamp = CtfInteger.ReadInt <ulong>(compactTimestamp, _buffer, compactTimestamp.BitOffset);
                    ulong prevLowerBits   = lastTimestamp & lowMask;

                    if (prevLowerBits < uint27timestamp)
                    {
                        timestamp = (lastTimestamp & highMask) | uint27timestamp;
                    }
                    else
                    {
                        timestamp  = (lastTimestamp & highMask) | uint27timestamp;
                        timestamp += overflowBit;
                    }
                }

                lastTimestamp = timestamp;

                CtfEvent evt = _streamDefinition.Events[(int)event_id];
                _header.Event     = evt;
                _header.Timestamp = timestamp;

                if (eventContext != null)
                {
                    ReadStruct(eventContext);

                    if (pid != null)
                    {
                        _header.Pid = CtfInteger.ReadInt <int>(pid, _buffer, pid.BitOffset);
                    }

                    if (tid != null)
                    {
                        _header.Tid = CtfInteger.ReadInt <int>(tid, _buffer, tid.BitOffset);
                    }

                    bool matches           = true;
                    int  processNameOffset = processName.BitOffset >> 3;

                    if (_buffer[processNameOffset] == 0)
                    {
                        lastProcessName = string.Empty;
                    }
                    else
                    {
                        int len = 0;
                        for (; len < processLen && _buffer[processNameOffset + len] != 0; len++)
                        {
                            if (len >= lastProcessName.Length)
                            {
                                matches = false;
                            }
                            else
                            {
                                matches &= lastProcessName[len] == _buffer[processNameOffset + len];
                            }
                        }

                        if (!matches || len != lastProcessName.Length)
                        {
                            lastProcessName = Encoding.UTF8.GetString(_buffer, processName.BitOffset >> 3, len);
                        }
                    }

                    _header.ProcessName = lastProcessName;
                }

                _readHeader = true;
                yield return(_header);
            }
        }
Ejemplo n.º 9
0
        public void ReadTypeIntoBuffer(CtfStruct context, CtfMetadataType type)
        {
            Align(type.Align);

            type.BitOffset = _bitOffset;

            if (type.CtfType == CtfTypes.Enum)
            {
                type           = ((CtfEnum)type).Type;
                type.BitOffset = _bitOffset;
            }
            else if (type.CtfType != CtfTypes.Struct && type.CtfType != CtfTypes.Variant)
            {
                int size = type.GetSize();
                if (size != CtfEvent.SizeIndeterminate)
                {
                    ReadBits(size);
                    return;
                }
            }

            switch (type.CtfType)
            {
            case CtfTypes.Array:
                CtfArray array = (CtfArray)type;

                var indexType = context.GetField(array.Index).Type;
                int len       = CtfInteger.ReadInt <int>(indexType, _buffer, indexType.BitOffset);

                int elemSize = array.Type.GetSize();
                if (elemSize == CtfEvent.SizeIndeterminate)
                {
                    for (int j = 0; j < len; j++)
                    {
                        ReadTypeIntoBuffer(null, array.Type);
                    }
                }
                else
                {
                    for (int j = 0; j < len; j++)
                    {
                        Align(type.Align);
                        ReadBits(elemSize);
                    }
                }
                break;

            case CtfTypes.Float:
                CtfFloat flt = (CtfFloat)type;
                ReadBits(flt.Exp + flt.Mant);
                break;

            case CtfTypes.Integer:
                CtfInteger ctfInt = (CtfInteger)type;
                ReadBits(ctfInt.Size);
                break;

            case CtfTypes.String:
                Debug.Assert((_bitOffset % 8) == 0);
                int startOffset = _bitOffset >> 3;
                int offset      = startOffset;

                ReadBits(8);
                bool ascii = ((CtfString)type).IsAscii;
                if (ascii)
                {
                    while (_buffer[offset++] != 0)
                    {
                        ReadBits(8);
                    }
                }
                else
                {
                    byte b = _buffer[offset];
                    while (b != 0)
                    {
                        switch (b)
                        {
                        default:
                            break;

                        case 0xc:
                        case 0xd:
                            ReadBits(8);
                            break;

                        case 0xe:
                            ReadBits(16);
                            break;

                        case 0xf:
                            ReadBits(24);
                            break;
                        }

                        offset = ReadBits(8) >> 3;
                        b      = _buffer[offset];
                    }
                }

                int bufferLen = (_bitOffset >> 3) - startOffset;

                Encoding encoding = ascii ? Encoding.ASCII : Encoding.UTF8;

                byte[] newArr = Encoding.Convert(encoding, Encoding.Unicode, _buffer, startOffset, bufferLen);
                ((CtfString)type).Length = bufferLen;

                if (_buffer.Length < _bufferLength + newArr.Length)
                {
                    byte[] buffer = ReallocateBuffer(_bufferLength + newArr.Length);
                    System.Buffer.BlockCopy(buffer, 0, _buffer, 0, _bufferLength);
                }

                System.Buffer.BlockCopy(newArr, 0, _buffer, startOffset, newArr.Length);
                _bufferLength = startOffset + newArr.Length;
                _bitOffset    = _bufferLength * 8;

                break;


            case CtfTypes.Struct:
                ReadStruct((CtfStruct)type);
                break;

            case CtfTypes.Variant:
                CtfVariant var = (CtfVariant)type;

                CtfField field    = context.GetField(var.Switch);
                CtfEnum  enumType = (CtfEnum)field.Type;

                int    value = CtfInteger.ReadInt <int>(enumType, _buffer, enumType.BitOffset);
                string name  = enumType.GetName(value);

                field = var.GetVariant(name);
                ReadTypeIntoBuffer(null, field.Type);
                break;

            default:
                throw new InvalidOperationException();
            }
        }
Ejemplo n.º 10
0
        private CtfMetadataType ParseOneType(string statement, out int index)
        {
            CtfMetadataType type = null;
            Match           match;

            if ((match = s_integer.Match(statement)).Success)
            {
                Group          group = match.Groups[1];
                CtfPropertyBag bag   = GetPropertyBag(group.ToString());

                type  = new CtfInteger(bag);
                index = group.Index + group.Length;
            }
            else if ((match = s_struct.Match(statement)).Success)
            {
                var group = match.Groups[1];

                if (group.ToString() != "{")
                {
                    throw new InvalidOperationException();
                }

                int open  = group.Index;
                int close = FindCloseBrace(statement, open);

                CtfField[] fields = ParseStructFields(statement, open, close).ToArray();

                type  = new CtfStruct(null, fields);
                index = close + 1;
            }
            else if ((match = s_float.Match(statement)).Success)
            {
                int open  = match.Index + match.Length - 1;
                int close = FindCloseBrace(statement, open);

                CtfPropertyBag bag = GetPropertyBag(statement, open, close);
                type  = new CtfFloat(bag);
                index = close + 1;
            }
            else if ((match = s_variant.Match(statement)).Success)
            {
                string switchVariable = match.Groups[1].ToString();

                int open  = statement.IndexOf('{');
                int close = FindCloseBrace(statement, open);

                if (close == -1)
                {
                    throw new InvalidOperationException();
                }


                CtfField[] fields = ParseStructFields(statement, open, close).ToArray();

                type  = new CtfVariant(switchVariable, fields);
                index = close + 1;
            }
            else if ((match = s_variable.Match(statement)).Success)
            {
                var typeGroup = match.Groups[1];

                string typeName = typeGroup.ToString().Trim();
                if (typeName == "string")
                {
                    type = new CtfString();
                }
                else
                {
                    type = new CtfUnresolvedType(typeName);
                }

                index = typeGroup.Index + typeGroup.Length;
            }
            else if ((match = s_enum.Match(statement)).Success)
            {
                var    groups   = match.Groups;
                string typeName = groups[1].ToString().Trim();

                int open  = statement.IndexOf('{');
                int close = FindCloseBrace(statement, open);
                if (close == -1)
                {
                    throw new InvalidOperationException();
                }

                CtfNamedRange[] ranges = ParseNamedRanges(statement, open + 1, close).ToArray();

                // TODO: Can enums just be an inline defined integer?
                type  = new CtfEnum(new CtfUnresolvedType(typeName), ranges);
                index = close + 1;
            }
            else
            {
                // TODO:  Floating point

                index = 0;
                return(null);
            }

            return(type);
        }
Ejemplo n.º 11
0
        public IEnumerable <CtfEventHeader> EnumerateEventHeaders()
        {
            CtfStruct  header   = _streamDefinition.EventHeader;
            CtfVariant v        = (CtfVariant)header.GetField("v").Type;
            CtfStruct  extended = (CtfStruct)v.GetVariant("extended").Type;
            CtfStruct  compact  = (CtfStruct)v.GetVariant("compact").Type;

            ulong lowMask = 0, highMask = 0, overflowBit = 0;
            ulong lastTimestamp = 0;

            StringBuilder processName = new StringBuilder();

            while (!_eof)
            {
                if (_readHeader)
                {
                    throw new InvalidOperationException("Must read an events data before reading the header again.");
                }

                _header.Clear();
                ResetBuffer();

                object[] result = ReadStruct(header);
                if (_eof)
                {
                    break;
                }

                ulong   timestamp;
                CtfEnum en       = (CtfEnum)header.GetField("id").Type;
                uint    event_id = header.GetFieldValue <uint>(result, "id");

                result = header.GetFieldValue <object[]>(result, "v");
                if (en.GetName((int)event_id) == "extended")
                {
                    event_id  = extended.GetFieldValue <uint>(result, "id");
                    timestamp = extended.GetFieldValue <ulong>(result, "timestamp");
                }
                else
                {
                    if (overflowBit == 0)
                    {
                        CtfInteger compactTimestamp = (CtfInteger)compact.GetField("timestamp").Type;
                        overflowBit = (1ul << compactTimestamp.Size);
                        lowMask     = overflowBit - 1;
                        highMask    = ~lowMask;
                    }

                    ulong uint27timestamp = compact.GetFieldValue <ulong>(result, "timestamp");
                    ulong prevLowerBits   = lastTimestamp & lowMask;

                    if (prevLowerBits < uint27timestamp)
                    {
                        timestamp = (lastTimestamp & highMask) | uint27timestamp;
                    }
                    else
                    {
                        timestamp  = (lastTimestamp & highMask) | uint27timestamp;
                        timestamp += overflowBit;
                    }
                }

                lastTimestamp = timestamp;

                CtfEvent evt = _streamDefinition.Events[(int)event_id];
                _header.Event     = evt;
                _header.Timestamp = timestamp;

                CtfStruct eventContext = _streamDefinition.EventContext;
                if (eventContext != null)
                {
                    result      = ReadStruct(eventContext);
                    _header.Pid = eventContext.GetFieldValue <int>(result, "_vpid");
                    _header.Tid = eventContext.GetFieldValue <int>(result, "_vtid");

                    int      procnameIndex = eventContext.GetFieldIndex("_procname");
                    object[] procname      = (object[])(result[procnameIndex]);
                    processName.Clear();
                    for (int i = 0; i < 17; i++)
                    {
                        sbyte b = (sbyte)procname[i];
                        if (b == 0)
                        {
                            break;
                        }

                        processName.Append((char)b);
                    }

                    _header.ProcessName = processName.ToString();
                }

                _readHeader = true;
                yield return(_header);
            }
        }