internal byte[] ParseDebuggerOutputText() { var byteOffset = (_command.ByteOffset % 4 == 0) ? _command.ByteOffset : _command.ByteOffset - (4 - _command.ByteOffset % 4); var lineOffset = _command.OutputOffset + (byteOffset / 4); var lineCount = _command.ByteCount / 4; var dataDwords = TextDebuggerOutputParser.ReadTextOutput(_filePath, lineOffset, lineCount); var dataBytes = new byte[dataDwords.Count * 4]; Buffer.BlockCopy(dataDwords.ToArray(), 0, dataBytes, 0, dataBytes.Length); return(dataBytes); }
private async Task <(StepResult, BreakState)> DoReadDebugDataAsync(ReadDebugDataStep step) { var watches = _debugWatches; BreakStateDispatchParameters dispatchParams = null; if (!string.IsNullOrEmpty(step.WatchesFile.Path)) { var result = await ReadDebugDataFileAsync("Valid watches", step.WatchesFile.Path, step.WatchesFile.IsRemote(), step.WatchesFile.CheckTimestamp); if (!result.TryGetResult(out var data, out var error)) { return(new StepResult(false, error.Message, ""), null); } var watchString = Encoding.UTF8.GetString(data); var watchArray = watchString.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); watches = Array.AsReadOnly(watchArray); } if (!string.IsNullOrEmpty(step.DispatchParamsFile.Path)) { var result = await ReadDebugDataFileAsync("Dispatch parameters", step.DispatchParamsFile.Path, step.DispatchParamsFile.IsRemote(), step.DispatchParamsFile.CheckTimestamp); if (!result.TryGetResult(out var data, out var error)) { return(new StepResult(false, error.Message, ""), null); } var paramsString = Encoding.UTF8.GetString(data); var dispatchParamsResult = BreakStateDispatchParameters.Parse(paramsString); if (!dispatchParamsResult.TryGetResult(out dispatchParams, out error)) { return(new StepResult(false, error.Message, ""), null); } } { var outputPath = step.OutputFile.Path; var initOutputTimestamp = GetInitialFileTimestamp(outputPath); int GetDispatchDwordCount(int fileDwordCount, out string warning) { warning = ""; if (dispatchParams == null) { return(fileDwordCount); } var laneDataSize = 1 /* system watch */ + watches.Count; var totalLaneCount = dispatchParams.GridSizeX * dispatchParams.GridSizeY * dispatchParams.GridSizeZ; var dispatchDwordCount = (int)totalLaneCount * laneDataSize; if (fileDwordCount < dispatchDwordCount) { warning = $"Output file ({outputPath}) is smaller than expected.\r\n\r\n" + $"Grid size as specified in the dispatch parameters file is ({dispatchParams.GridSizeX}, {dispatchParams.GridSizeY}, {dispatchParams.GridSizeZ}), " + $"which corresponds to {totalLaneCount} lanes. With {laneDataSize} DWORDs per lane, the output file is expected to contain at least " + $"{dispatchDwordCount} DWORDs, but it only contains {fileDwordCount} DWORDs."; } return(Math.Min(dispatchDwordCount, fileDwordCount)); } BreakStateOutputFile outputFile; uint[] localOutputData = null; string stepWarning; if (step.OutputFile.IsRemote()) { var response = await _channel.SendWithReplyAsync <MetadataFetched>( new FetchMetadata { FilePath = new[] { outputPath }, BinaryOutput = step.BinaryOutput }, _controller.CancellationToken); if (response.Status == FetchStatus.FileNotFound) { return(new StepResult(false, $"Output file ({outputPath}) could not be found.", ""), null); } if (step.OutputFile.CheckTimestamp && response.Timestamp == initOutputTimestamp) { return(new StepResult(false, $"Output file ({outputPath}) was not modified. Data may be stale.", ""), null); } var offset = step.BinaryOutput ? step.OutputOffset : step.OutputOffset * 4; var fileByteCount = Math.Max(0, response.ByteCount - offset); var dispatchDwordCount = GetDispatchDwordCount(fileDwordCount: fileByteCount / 4, out stepWarning); outputFile = new BreakStateOutputFile(outputPath, step.BinaryOutput, step.OutputOffset, response.Timestamp, dispatchDwordCount); } else { var timestamp = GetLocalFileLastWriteTimeUtc(outputPath); if (step.OutputFile.CheckTimestamp && timestamp == initOutputTimestamp) { return(new StepResult(false, $"Output file ({outputPath}) was not modified. Data may be stale.", ""), null); } int dispatchDwordCount; if (step.BinaryOutput) { if (!ReadLocalFile(outputPath, out var outputBytes, out var readError)) { return(new StepResult(false, "Output file could not be opened. " + readError, ""), null); } var fileByteCount = Math.Max(0, outputBytes.Length - step.OutputOffset); dispatchDwordCount = GetDispatchDwordCount(fileDwordCount: fileByteCount / 4, out stepWarning); localOutputData = new uint[dispatchDwordCount]; Buffer.BlockCopy(outputBytes, step.OutputOffset, localOutputData, 0, dispatchDwordCount * 4); } else { var outputDwords = TextDebuggerOutputParser.ReadTextOutput(outputPath, step.OutputOffset); dispatchDwordCount = GetDispatchDwordCount(fileDwordCount: outputDwords.Count, out stepWarning); if (outputDwords.Count > dispatchDwordCount) { outputDwords.RemoveRange(dispatchDwordCount, outputDwords.Count - dispatchDwordCount); } localOutputData = outputDwords.ToArray(); } outputFile = new BreakStateOutputFile(outputPath, step.BinaryOutput, offset: 0, timestamp, dispatchDwordCount); } var data = new BreakStateData(watches, outputFile, localOutputData); return(new StepResult(true, stepWarning, ""), new BreakState(data, dispatchParams)); } }