private void Dump() { using (GXDebugStream stream = new GXDebugStream(FileName, FileMode.Open)) { GXDebugItem[] items; Guid SessionGuid; GXDebugGenId GenId; IList <GXDebugError> errors = new List <GXDebugError>(); long lastPosition = stream.Position; while ((items = ReadItems(stream, out SessionGuid, out GenId, errors)) != null) { DumpAndClearErrors(errors); if (items.Length > 0) { Console.WriteLine($"SessionGuid: { SessionGuid } - Gen: { GenId}"); Console.WriteLine($"Item Count: { items.Length } - bits/message: { (int)(((stream.Position - lastPosition) << 3) / items.Length) }"); for (int idx = 0; idx < items.Length; idx++) { Console.WriteLine($"\tItem({ idx }): { items[idx] }"); } Console.WriteLine(); } lastPosition = stream.Position; } DumpAndClearErrors(errors); } }
private GXDebugItem[] ReadItems(GXDebugStream stream, out Guid sessionGuid, out GXDebugGenId genId, IList <GXDebugError> errors) { sessionGuid = Guid.Empty; genId = GXDebugGenId.INVALID; stream.InitializeNewBlock(); if (!FindEscape(stream, GXDebugStream.ESCAPE.PROLOG, errors)) { return(null); } short versionAndGenId = stream.ReadVLUShort(); genId = (GXDebugGenId)(versionAndGenId & 0xF); short version = (short)(versionAndGenId >> 4); if (version != GXDebugManager.GXDEBUG_VERSION) { errors.Add(new GXDebugError(stream.Position, $"Cannot parse version { version } blocks")); FindEscape(stream, GXDebugStream.ESCAPE.EPILOG, errors); return(new GXDebugItem[0]); } int itemCount = stream.ReadVLUInt(); if (itemCount == 0) { errors.Add(new GXDebugError(stream.Position, $"Invalid block. Item count = 0")); FindEscape(stream, GXDebugStream.ESCAPE.EPILOG, errors); return(new GXDebugItem[0]); } byte[] guid = new byte[16]; sessionGuid = new Guid(stream.ReadFully(guid)); GXDebugItem[] items = new GXDebugItem[itemCount]; for (int idx = 0; idx < itemCount; idx++) { items[idx] = ReadItem(stream, errors); if (items[idx].MsgType == GXDebugMsgType.INVALID) { while (++idx < itemCount) { items[idx] = NewInvalidItem(); } break; } } FindEscape(stream, GXDebugStream.ESCAPE.EPILOG, errors); return(items); }
private bool FindEscape(GXDebugStream stream, GXDebugStream.ESCAPE escape, IList <GXDebugError> errors) { int byteValue; int escapeCount = 0; long errLoc = stream.Position; while ((byteValue = stream.ReadRaw()) != -1) { if (byteValue == 0xFF) { escapeCount++; if (escapeCount == 3) { byteValue = stream.ReadRaw(); if (byteValue != -1 && (byte)byteValue == escape.ToByte()) { return(true); } else { if (errLoc != -1) { errors.Add(new GXDebugError(errLoc, $"Cannot find escape sequence. Looking for { escape.ToByte() }, got { byteValue }")); errLoc = -1; } escapeCount = 0; } } } else { escapeCount = 0; } } if (stream.Position != errLoc && errLoc != -1) { errors.Add(new GXDebugError(errLoc, "Cannot find escape sequence")); } return(false); }
private void mSave(object state1) { object[] state = state1 as object[]; GXDebugItem[] Data = state[0] as GXDebugItem[]; int saveTop = (int)state[1]; int saveCount = (int)state[2]; lock (mSaveLock) { int idx = 0; try { string FQFileName = Path.IsPathRooted(FileName) ? FileName : Path.Combine(GxContext.Current.GetPhysicalPath(), FileName); #pragma warning disable SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}' using (GXDebugStream stream = new GXDebugStream(FQFileName, FileMode.Append)) #pragma warning restore SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}' { stream.WriteHeader(SessionGuid, (short)(GXDEBUG_VERSION << 4 | GENERATOR_ID.ToByte()), saveCount); #if _DEBUG_DEBUGGER Console.WriteLine("mSave-" + saveTop); #endif for (; idx < saveTop; idx++) { GXDebugItem dbgItem = Data[idx]; #if _DEBUG_DEBUGGER Console.WriteLine($"item({idx}): { dbgItem }"); #endif switch (dbgItem.MsgType) { case GXDebugMsgType.SYSTEM: { stream.WriteByte((byte)(dbgItem.MsgType.ToByte() | ((GXDebugMsgCode)dbgItem.Arg1).ToByte())); switch ((GXDebugMsgCode)dbgItem.Arg1) { case GXDebugMsgCode.INITIALIZE: stream.WriteLong(((DateTime)dbgItem.ArgObj).ToUniversalTime().Ticks); break; case GXDebugMsgCode.OBJ_CLEANUP: stream.WriteVLUInt((int)dbgItem.ArgObj); break; case GXDebugMsgCode.EXIT: break; case GXDebugMsgCode.PGM_INFO: KeyValuePair <object, object> info = (KeyValuePair <object, object>)dbgItem.ArgObj; stream.WriteVLUInt(((KeyValuePair <int, int>)info.Key).Key); stream.WriteVLUInt(((KeyValuePair <int, int>)info.Key).Value); stream.WriteVLUInt(((KeyValuePair <int, long>)info.Value).Key); stream.WriteInt(((KeyValuePair <int, long>)info.Value).Value); break; default: throw new ArgumentException($"Invalid DbgItem: { dbgItem }"); } } break; case GXDebugMsgType.PGM_TRACE: { stream.WritePgmTrace(dbgItem.DbgInfo.SId, dbgItem.Arg1, dbgItem.Arg2, dbgItem.Ticks); } break; case GXDebugMsgType.PGM_TRACE_RANGE: case GXDebugMsgType.PGM_TRACE_RANGE_WITH_COLS: { stream.WriteByte(dbgItem.MsgType.ToByte()); stream.WriteVLUInt(dbgItem.DbgInfo.SId); stream.WriteVLUInt(dbgItem.Arg1); stream.WriteVLUInt(dbgItem.Arg2); if (dbgItem.MsgType == GXDebugMsgType.PGM_TRACE_RANGE_WITH_COLS) { stream.WriteVLUInt(((KeyValuePair <int, int>)dbgItem.ArgObj).Key); stream.WriteVLUInt(((KeyValuePair <int, int>)dbgItem.ArgObj).Value); } } break; case GXDebugMsgType.REGISTER_PGM: { stream.WriteByte(dbgItem.MsgType.ToByte()); stream.WriteVLUInt(dbgItem.DbgInfo.SId); stream.WriteVLUInt(dbgItem.Arg1); stream.WriteVLUInt(((KeyValuePair <int, int>)dbgItem.ArgObj).Key); stream.WriteVLUInt(((KeyValuePair <int, int>)dbgItem.ArgObj).Value); } break; case GXDebugMsgType.SKIP: continue; } ClearDebugItem(dbgItem); } } } catch (Exception ex) { GXLogging.Warn(log, $"GXDebugManager: Cannot write debug file", ex); } saving = false; waitSaveEvent.Set(); } }
private GXDebugItem ReadItem(GXDebugStream stream, IList <GXDebugError> errors) { int value; if ((value = stream.ReadByte()) == -1) { throw new EndOfStreamException(); } GXDebugItem dbgItem = new GXDebugItem(); if ((value & GXDebugMsgType.SYSTEM.ToByte()) == GXDebugMsgType.SYSTEM.ToByte()) { switch (value & 0xFC) { case 0xC0: { dbgItem.MsgType = GXDebugMsgType.REGISTER_PGM; dbgItem.DbgInfo = new GXDebugInfoLocal(); dbgItem.DbgInfo.SId = stream.ReadVLUInt(); dbgItem.Arg1 = stream.ReadVLUInt(); dbgItem.ArgObj = new KeyValuePair <int, int>(stream.ReadVLUInt(), stream.ReadVLUInt()); } break; case 0xA0: { dbgItem.MsgType = GXDebugMsgType.PGM_TRACE_RANGE; dbgItem.DbgInfo = new GXDebugInfoLocal(); dbgItem.DbgInfo.SId = stream.ReadVLUInt(); dbgItem.Arg1 = stream.ReadVLUInt(); dbgItem.Arg2 = stream.ReadVLUInt(); if ((value & GXDebugMsgType.PGM_TRACE_RANGE_WITH_COLS.ToByte()) == GXDebugMsgType.PGM_TRACE_RANGE_WITH_COLS.ToByte()) { dbgItem.ArgObj = new KeyValuePair <int, int>(stream.ReadVLUInt(), stream.ReadVLUInt()); } else { dbgItem.ArgObj = new KeyValuePair <int, int>(0, 0); } } break; case 0x80: { dbgItem.MsgType = GXDebugMsgType.SYSTEM; dbgItem.Arg1 = value & GXDebugMsgCode.MASK_BITS.ToByte(); switch ((GXDebugMsgCode)(dbgItem.Arg1)) { case GXDebugMsgCode.INITIALIZE: dbgItem.ArgObj = new DateTime(stream.ReadLong(), DateTimeKind.Utc); break; case GXDebugMsgCode.OBJ_CLEANUP: dbgItem.ArgObj = stream.ReadVLUInt(); break; case GXDebugMsgCode.PGM_INFO: { KeyValuePair <int, int> pgmKey = new KeyValuePair <int, int>(stream.ReadVLUInt(), stream.ReadVLUInt()); KeyValuePair <int, long> pgmInfo = new KeyValuePair <int, long>(stream.ReadVLUInt(), stream.ReadIntAsLong()); dbgItem.ArgObj = new KeyValuePair <object, object>(pgmKey, pgmInfo); } break; case GXDebugMsgCode.EXIT: break; default: dbgItem.MsgType = GXDebugMsgType.INVALID; errors.Add(new GXDebugError(stream.Position, $"Invalid Debug Item (type={ dbgItem.MsgType } - { value })")); break; } } break; default: dbgItem.MsgType = GXDebugMsgType.INVALID; errors.Add(new GXDebugError(stream.Position, $"Invalid Debug Item (type={ value })")); break; } } else { stream.ReadPgmTrace(dbgItem, (byte)value); } return(dbgItem); }