StackItem GetStackItem (StatInfo info) { switch (info.Code) { case StatCode.Method: if (info.Id == 0 || info.Id > methods.Length) return StackItem.Unknown; return methods [info.Id]; case StatCode.UnmanagedFunctionId: if (info.Id == 0 || info.Id > functions.Length) return StackItem.Unknown; return functions [info.Id]; case StatCode.UnmanagedFunctionNewId: AddFunction (info.Id, info.Name, regions [info.Region].Filename); return functions [info.Id]; case StatCode.UnmanagedFunctionOffsetInRegion: return StackItem.Unknown; default: throw new Exception ("Unexpected stat code " + info.Code); } }
void AddChain (StatInfo chain, StackItem last_hit) { if (last_hit == null) throw new Exception ("Unexpected call chain"); List<StackItem> items = new List<StackItem> (); foreach (StatInfo caller in chain.Chain) items.Insert (0, GetStackItem (caller)); items.Add (last_hit); stack.AddTrace (items); }
internal StatBlock(Buffer raw) : base(BlockCode.Statistical) { start_counter = raw.ReadUlong (); start_time = raw.ReadTime (); for (uint id = raw.ReadUint (); id != 0; id = raw.ReadUint ()) { StatInfo info = new StatInfo ((StatCode) (id & 0x7)); uint data = id >> 3; switch (info.Code) { case StatCode.Method: case StatCode.UnmanagedFunctionId: info.Id = data; break; case StatCode.UnmanagedFunctionNewId: info.Region = data; info.Id = raw.ReadUint (); info.Name = raw.ReadString (); break; case StatCode.UnmanagedFunctionOffsetInRegion: info.Region = data; if (data != 0) info.Offset = raw.ReadUint (); else info.Address = raw.ReadUlong (); break; case StatCode.CallChain: info.Chain = new List<StatInfo> (); for (int i = 0; i < data; i++) { uint nid = raw.ReadUint (); StatInfo ninfo = new StatInfo ((StatCode) (nid & 0x7)); uint ndata = nid >> 3; switch (ninfo.Code) { case StatCode.Method: case StatCode.UnmanagedFunctionId: ninfo.Id = ndata; break; case StatCode.UnmanagedFunctionNewId: ninfo.Region = ndata; ninfo.Id = raw.ReadUint (); ninfo.Name = raw.ReadString (); break; case StatCode.UnmanagedFunctionOffsetInRegion: ninfo.Region = ndata; if (ndata != 0) ninfo.Offset = raw.ReadUint (); else ninfo.Address = raw.ReadUlong (); break; default: throw new Exception ("unexpected code in call chain " + ninfo.Code); } info.Chain.Insert (0, ninfo); } break; case StatCode.Regions: for (uint region = raw.ReadUint (); region != 0; region = raw.ReadUint ()) info.InvalidRegions.Add (region); for (uint region = raw.ReadUint (); region != 0; region = raw.ReadUint ()) info.Regions.Add (new RegionInfo (region, raw.ReadUlong (), raw.ReadUint (), raw.ReadUint (), raw.ReadString ())); break; default: throw new Exception ("Unexpected code " + info.Code); } items.Add (info); } end_counter = raw.ReadUlong (); end_time = raw.ReadTime (); if (!raw.IsEmpty) throw new Exception ("Unexpected data remaining in block"); }