Exemplo n.º 1
0
        private void StepDecoder()
        {
            ulong pos    = m_ReadPos;
            ulong maxpos = m_WritePos;

            if (m_SeenStringRollback > 0)
            {
                m_SeenStrings.RemoveRange(m_SeenStrings.Count - m_SeenStringRollback, m_SeenStringRollback);
                m_SeenStringRollback = 0;
            }

            if (m_SeenStackRollback > 0)
            {
                m_SeenStacks.RemoveRange(m_SeenStacks.Count - m_SeenStackRollback, m_SeenStackRollback);
                m_SeenStackRollback = 0;
            }

            while (pos < maxpos)
            {
                if (!ReadUnsigned(out m_CurrCode, ref pos))
                {
                    return;
                }

                if (!Enum.IsDefined(typeof(EventCode), (EventCode)m_CurrCode))
                {
                    throw new IOException(String.Format("Bad event code {0} at pos {1}\n", m_CurrCode, pos - 1));
                }

                if (!ReadUnsigned(out m_CurrScope, ref pos))
                {
                    return;
                }

                if (0 != m_CurrScope)
                {
                    if (!ReadStringIndex(out m_CurrScopeDataIndex, ref pos))
                    {
                        return;
                    }
                }
                else
                {
                    m_CurrScopeDataIndex = -1;
                }

                ulong timestamp;
                if (!ReadUnsigned(out timestamp, ref pos))
                {
                    return;
                }

                // Only commit after the whole thing read successfully, as the UI thread could sample the
                // timestamp at any time to put in a trace marker.
                m_CurrTimestamp = timestamp;

                if (!ReadBackTraceIndex(out m_CurrBackTraceIndex, ref pos))
                {
                    return;
                }

                switch ((EventCode)m_CurrCode)
                {
                case EventCode.BeginStream:
                    string pname;
                    ulong  ptrsize;
                    ulong  magic;
                    ulong  timer_freq;
                    ulong  well_known_address;
                    if (!ReadUnsigned(out magic, ref pos))
                    {
                        return;
                    }
                    if (magic != StreamMagic)
                    {
                        throw new IOException(String.Format("Bad stream magic {0:x8}, expected {1:x8}", magic, StreamMagic));
                    }

                    if (!ReadString(out pname, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out ptrsize, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out timer_freq, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out well_known_address, ref pos))
                    {
                        return;
                    }
                    MetaData.PlatformName              = pname;
                    MetaData.PointerSizeBytes          = (int)ptrsize;
                    MetaData.TimerFrequency            = timer_freq;
                    MetaData.MemTraceInitCommonAddress = well_known_address;
                    // Nothing written.
                    break;

                case EventCode.EndStream:
                    // Nothing written.
                    break;

                case EventCode.ModuleDump:
                {
                    List <ModuleInfo> tmp = new List <ModuleInfo>();
                    for (; ;)
                    {
                        ulong ctrl;
                        if (!ReadUnsigned(out ctrl, ref pos))
                        {
                            return;
                        }
                        if (0 == ctrl)
                        {
                            break;
                        }

                        string modname;
                        ulong  modbase;
                        ulong  modsize;
                        if (!ReadString(out modname, ref pos))
                        {
                            return;
                        }
                        if (!ReadUnsigned(out modbase, ref pos))
                        {
                            return;
                        }
                        if (!ReadUnsigned(out modsize, ref pos))
                        {
                            return;
                        }

                        if (modname.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase))
                        {
                            MetaData.ExecutableName = Path.GetFileNameWithoutExtension(modname);
                        }

                        tmp.Add(new ModuleInfo {
                                BaseAddress = modbase, SizeBytes = modsize, Name = modname
                            });
                    }

                    // We got all of it. Commit.
                    MetaData.Modules = tmp;
                }
                    // Nothing written.
                    break;

                case EventCode.Mark:
                {
                    string name;
                    if (!ReadString(out name, ref pos))
                    {
                        return;
                    }
                    MetaData.AddMark(new TraceMark {
                            Name = name, TimeStamp = m_CurrTimestamp
                        });
                }
                    // Nothing written.
                    break;

                case EventCode.AddressAllocate:
                {
                    ulong addr, size;
                    int   name_index;

                    if (!ReadUnsigned(out addr, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out size, ref pos))
                    {
                        return;
                    }
                    if (!ReadStringIndex(out name_index, ref pos))
                    {
                        return;
                    }

                    if (!m_AddressCreateEvents.ContainsKey(addr))
                    {
                        m_AddressCreateEvents[addr] = m_Out.BaseStream.Position;
                        BeginOutEvent();
                        m_Out.Write(addr);
                        m_Out.Write(size);
                        m_Out.Write(name_index);
                    }
                    else
                    {
                        MetaData.AddWarning("Attempt to allocate already allocated virtual address {0:x16}", addr);
                    }
                }
                break;

                case EventCode.AddressFree:
                {
                    ulong addr;
                    if (!ReadUnsigned(out addr, ref pos))
                    {
                        return;
                    }

                    // Handle sloppy runtime code reporting frees multiple times :(
                    if (m_AddressCreateEvents.ContainsKey(addr))
                    {
                        BeginOutEvent();
                        m_Out.Write(addr);
                        m_Out.Write(m_AddressCreateEvents[addr]);
                        m_AddressCreateEvents.Remove(addr);
                    }
                    else
                    {
                        MetaData.AddWarning("Attempt to free non-allocated virtual address {0:x16}", addr);
                    }
                }
                break;

                case EventCode.VirtualCommit:
                case EventCode.VirtualDecommit:
                {
                    ulong addr, size;
                    if (!ReadUnsigned(out addr, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out size, ref pos))
                    {
                        return;
                    }
                    BeginOutEvent();
                    m_Out.Write(addr);
                    m_Out.Write(size);
                }
                break;

                case EventCode.HeapCreate:
                {
                    ulong id;
                    int   str_index;
                    if (!ReadUnsigned(out id, ref pos))
                    {
                        return;
                    }
                    if (!ReadStringIndex(out str_index, ref pos))
                    {
                        return;
                    }
                    m_HeapCreateEvents[id] = m_Out.BaseStream.Position;
                    BeginOutEvent();
                    m_Out.Write(id);
                    m_Out.Write(str_index);
                }
                break;

                case EventCode.HeapDestroy:
                {
                    ulong id;
                    if (!ReadUnsigned(out id, ref pos))
                    {
                        return;
                    }
                    if (m_HeapCreateEvents.ContainsKey(id))
                    {
                        BeginOutEvent();
                        m_Out.Write(id);
                        m_Out.Write(m_HeapCreateEvents[id]);
                        m_HeapCreateEvents.Remove(id);
                    }
                    else
                    {
                        MetaData.AddWarning("Attempt to destroy non-existing heap id={0:x16}", id);
                    }
                }
                break;

                case EventCode.HeapAddCore:
                case EventCode.HeapRemoveCore:
                {
                    ulong id, addr, size;
                    if (!ReadUnsigned(out id, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out addr, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out size, ref pos))
                    {
                        return;
                    }
                    BeginOutEvent();
                    m_Out.Write(id);
                    m_Out.Write(addr);
                    m_Out.Write(size);
                }
                break;

                case EventCode.HeapAllocate:
                {
                    ulong addr, size, heap_id;
                    if (!ReadUnsigned(out heap_id, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out addr, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out size, ref pos))
                    {
                        return;
                    }
                    var key = new AllocationKey {
                        HeapId = heap_id, Address = addr
                    };
                    if (!m_AllocCreateEvents.ContainsKey(key))
                    {
                        m_AllocCreateEvents[key] = m_Out.BaseStream.Position;
                        BeginOutEvent();
                        m_Out.Write((uint)heap_id);
                        m_Out.Write(addr);
                        m_Out.Write(size);
                    }
                    else
                    {
                        MetaData.AddWarning("Attempt to allocate already-allocated address {0:x16}", addr);
                    }
                }
                break;

                case EventCode.HeapReallocate:
                {
                    ulong heap_id, old_addr, new_addr, new_size;
                    if (!ReadUnsigned(out heap_id, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out old_addr, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out new_addr, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out new_size, ref pos))
                    {
                        return;
                    }
                    long npos = m_Out.BaseStream.Position;
                    var  key  = new AllocationKey {
                        HeapId = heap_id, Address = old_addr
                    };
                    if (m_AllocCreateEvents.ContainsKey(key))
                    {
                        BeginOutEvent();
                        m_Out.Write((uint)heap_id);
                        m_Out.Write(old_addr);
                        m_Out.Write(new_addr);
                        m_Out.Write(new_size);
                        m_Out.Write(m_AllocCreateEvents[key]);
                        m_AllocCreateEvents.Remove(key);
                        var new_key = new AllocationKey {
                            HeapId = heap_id, Address = new_addr
                        };
                        m_AllocCreateEvents[new_key] = npos;
                    }
                    else
                    {
                        MetaData.AddWarning("Attempt to reallocate non-allocated address {0:x16}", old_addr);
                    }
                    break;
                }

                case EventCode.HeapFree:
                {
                    ulong addr, heap_id;
                    if (!ReadUnsigned(out heap_id, ref pos))
                    {
                        return;
                    }
                    if (!ReadUnsigned(out addr, ref pos))
                    {
                        return;
                    }
                    if (addr != 0)
                    {
                        var key = new AllocationKey {
                            HeapId = heap_id, Address = addr
                        };
                        if (m_AllocCreateEvents.ContainsKey(key))
                        {
                            BeginOutEvent();
                            m_Out.Write((uint)heap_id);
                            m_Out.Write(addr);
                            m_Out.Write(m_AllocCreateEvents[key]);
                            m_AllocCreateEvents.Remove(key);
                        }
                        else
                        {
                            MetaData.AddWarning("Attempt to free non-allocated address {0:x16}", addr);
                        }
                    }
                }
                break;

                default:
                    throw new IOException(String.Format("Unexpected event code {0}", m_CurrCode));
                }

                // Commit data decoded so far
                m_ReadPos             = pos;
                m_SeenStringRollback  = 0;
                m_SeenStackRollback   = 0;
                MetaData.MaxTimeStamp = m_CurrTimestamp;
                ++MetaData.EventCount;
            }
        }