public DebugBytecodeContainer(DebugBytecodeReader reader) { try { Chunks = new List <DebugBytecodeChunk>(); _reader = reader; var magicNumber = reader.PeakUint32(); if (magicNumber == 0xFEFF2001) { Chunks.Add(DebugEffectChunk.Parse(reader, (uint)reader.Count)); return; } Header = DebugBytecodeContainerHeader.Parse(reader); for (uint i = 0; i < Header.ChunkCount; i++) { uint chunkOffset = reader.ReadUInt32("chunkOffset"); var fourCC = DebugUtil.ToReadable(reader.PeakUInt32At((int)chunkOffset).ToFourCcString()); var chunkReader = reader.CopyAtOffset($"Chunk{fourCC}", reader, (int)chunkOffset); var chunk = DebugBytecodeChunk.ParseChunk(chunkReader, this); if (chunk != null) { Chunks.Add(chunk); } } } catch (Exception ex) { Exception = ex; Error = ex.ToString(); } }
public void DumpStructure(string relPath) { string file = $"{ShaderDirectory}/{relPath}"; // Arrange. // Act. var bytecode = File.ReadAllBytes(file + ".o"); var reader = new DebugParser.DebugBytecodeReader(bytecode, 0, bytecode.Length); string error = ""; try { if (bytecode[2] == 255 && bytecode[3] == 254) { reader.ReadByte("minorVersion"); reader.ReadByte("majorVersion"); reader.ReadUInt16("shaderType"); DebugEffectChunk.Parse(reader, (uint)(bytecode.Length - 4)); } else { var shaderModel = DebugShaderModel.Parse(reader); } } catch (Exception ex) { error = ex.ToString(); } var dump = reader.DumpStructure(); if (!string.IsNullOrEmpty(error)) { dump += "\n" + error; } File.WriteAllText($"{file}.d.txt", dump); var dumpHtml = ""; try { dumpHtml = reader.DumpHtml(); } catch (Exception ex) { } File.WriteAllText($"{file}.d.html", dumpHtml); if (!string.IsNullOrEmpty(error)) { Assert.That(false, error); } //Assert.That(!dump.Contains("Unread Memory"), "Unread memory found"); // Assert. }
public DebugBytecodeContainer(byte[] rawBytes) { try { _rawBytes = rawBytes; var reader = new DebugBytecodeReader(rawBytes, 0, rawBytes.Length); Chunks = new List <DebugBytecodeChunk>(); _reader = reader; var magicNumber = reader.PeekUint32(); if (magicNumber == 0xFEFF2001) { Chunks.Add(DebugEffectChunk.Parse(reader, (uint)rawBytes.Length)); return; } Header = DebugBytecodeContainerHeader.Parse(reader); for (uint i = 0; i < Header.ChunkCount; i++) { uint chunkOffset = reader.ReadUInt32("chunkOffset"); var fourCC = DebugUtil.ToReadable(reader.PeekUInt32At((int)chunkOffset).ToFourCcString()); var chunkReader = reader.CopyAtOffset($"Chunk{fourCC}", reader, (int)chunkOffset); var chunk = DebugBytecodeChunk.ParseChunk(chunkReader, this); if (chunk != null) { Chunks.Add(chunk); } } foreach (var chunk in Chunks.OfType <DebugPipelineStateValidationChunk>()) { chunk.UpdateVersion(Chunks.OfType <DebugDxilChunk>().First().Version); } } catch (Exception ex) { Exception = ex; Error = ex.ToString(); } }
static void Main(string[] args) { args = new string[] { "-O", "test.html", "-h", @"C:\Files\KM\ShaderStudio\src\UnityTests\bin\Debug\Blob\outer_wilds\Assets\Shader\SpritesDefault\VS_BF58DDF502C51FEB5145F1D0310B4327.o" }; var options = new Options(); for (int i = 0; i < args.Length; i++) { switch (args[i]) { case "-O": if (args.Length <= i + 1) { Console.Error.WriteLine("No output path specified"); return; } options.DestPath = args[i + 1]; i += 1; break; case "-a": options.Mode = DecompileMode.Dissassemble; break; case "-d": options.Mode = DecompileMode.Debug; break; case "-h": options.Mode = DecompileMode.DebugHtml; break; default: options.SourcePath = args[i]; break; } } if (string.IsNullOrEmpty(options.SourcePath)) { Console.Error.WriteLine("No source path specified"); Environment.Exit(1); } byte[] data = null; try { data = File.ReadAllBytes(options.SourcePath); } catch (Exception ex) { Console.Error.WriteLine("Error reading source"); Console.Error.WriteLine(ex); Environment.Exit(1); } var programType = GetProgramType(data); using (var sw = GetStream(options)) { if (programType == ProgramType.Unknown) { Console.Error.WriteLine($"Unable to identify shader object format"); Environment.Exit(1); } else if (programType == ProgramType.DXBC) { if (options.Mode == DecompileMode.Dissassemble) { var container = new BytecodeContainer(data); sw.Write(container.ToString()); } else if (options.Mode == DecompileMode.Decompile) { var hlsl = DXDecompiler.Decompile(data); sw.Write(hlsl); } else if (options.Mode == DecompileMode.Debug) { sw.WriteLine(string.Join(" ", args)); var shaderBytecode = DebugBytecodeContainer.Parse(data); var result = shaderBytecode.Dump(); sw.Write(result); } else if (options.Mode == DecompileMode.DebugHtml) { var shaderBytecode = DebugBytecodeContainer.Parse(data); var result = shaderBytecode.DumpHTML(); sw.Write(result); } } else if (programType == ProgramType.DX9) { if (options.Mode == DecompileMode.Dissassemble) { var disasm = SlimShader.DX9Shader.AsmWriter.Disassemble(data); sw.Write(disasm); } else if (options.Mode == DecompileMode.Decompile) { var hlsl = SlimShader.DX9Shader.HlslWriter.Decompile(data); sw.Write(hlsl); } else if (options.Mode == DecompileMode.Debug) { sw.WriteLine(string.Join(" ", args)); var shaderType = (SlimShader.DX9Shader.ShaderType)BitConverter.ToUInt16(data, 2); if (shaderType == SlimShader.DX9Shader.ShaderType.Effect) { var reader = new DebugBytecodeReader(data, 0, data.Length); string error = ""; try { reader.ReadByte("minorVersion"); reader.ReadByte("majorVersion"); reader.ReadUInt16("shaderType"); DebugEffectChunk.Parse(reader, (uint)(data.Length - 4)); } catch (Exception ex) { error = ex.ToString(); } var dump = reader.DumpStructure(); if (!string.IsNullOrEmpty(error)) { dump += "\n" + error; } sw.Write(dump); } else { var reader = new DebugBytecodeReader(data, 0, data.Length); string error = ""; try { DebugShaderModel.Parse(reader); } catch (Exception ex) { error = ex.ToString(); } var dump = reader.DumpStructure(); if (!string.IsNullOrEmpty(error)) { dump += "\n" + error; } sw.Write(dump); } } else if (options.Mode == DecompileMode.DebugHtml) { var shaderType = (SlimShader.DX9Shader.ShaderType)BitConverter.ToUInt16(data, 2); if (shaderType == SlimShader.DX9Shader.ShaderType.Effect) { var reader = new DebugBytecodeReader(data, 0, data.Length); string error = ""; try { reader.ReadByte("minorVersion"); reader.ReadByte("majorVersion"); reader.ReadUInt16("shaderType"); DebugEffectChunk.Parse(reader, (uint)(data.Length - 4)); } catch (Exception ex) { error = ex.ToString(); } var dump = reader.DumpHtml(); if (!string.IsNullOrEmpty(error)) { dump += "\n" + error; } sw.Write(dump); } else { var reader = new DebugBytecodeReader(data, 0, data.Length); string error = ""; try { DebugShaderModel.Parse(reader); } catch (Exception ex) { error = ex.ToString(); } var dump = reader.DumpHtml(); if (!string.IsNullOrEmpty(error)) { dump += "\n" + error; } sw.Write(dump); } } } } }
public static DebugBytecodeChunk ParseChunk(DebugBytecodeReader chunkReader, DebugBytecodeContainer container) { // Type of chunk this is. uint fourCc = BitConverter.ToUInt32(chunkReader.ReadBytes("fourCc", 4), 0); // Total length of the chunk in bytes. uint chunkSize = chunkReader.ReadUInt32("chunkSize"); ChunkType chunkType; if (KnownChunkTypes.ContainsKey(fourCc)) { chunkType = KnownChunkTypes[fourCc]; } else { System.Diagnostics.Debug.Assert(false, "Chunk type '" + fourCc.ToFourCcString() + "' is not yet supported."); System.Diagnostics.Debug.WriteLine("Chunk type '" + fourCc.ToFourCcString() + "' is not yet supported."); return(null); } var chunkContentReader = chunkReader.CopyAtCurrentPosition($"{fourCc.ToFourCcString()}", chunkReader, (int)chunkSize); DebugBytecodeChunk chunk = null; switch (chunkType) { case ChunkType.Ifce: chunk = DebugInterfacesChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Isgn: case ChunkType.Osgn: case ChunkType.Osg5: case ChunkType.Pcsg: case ChunkType.Isg1: case ChunkType.Osg1: chunk = DebugInputOutputSignatureChunk.Parse(chunkContentReader, chunkType, container.ResourceDefinition?.Target?.ProgramType ?? (SlimShader.Chunks.Common.ProgramType) 100); break; case ChunkType.Rdef: chunk = DebugResourceDefinitionChunk.Parse(chunkContentReader); break; case ChunkType.Sdbg: case ChunkType.Spdb: //chunk = DebuggingChunk.Parse(chunkContentReader, chunkType, (int)chunkSize); break; case ChunkType.Sfi0: chunk = DebugSfi0Chunk.Parse(chunkContentReader, null, chunkSize); break; case ChunkType.Shdr: case ChunkType.Shex: chunk = DebugShaderProgramChunk.Parse(chunkContentReader); break; case ChunkType.Stat: chunk = DebugStatisticsChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Xnas: case ChunkType.Xnap: case ChunkType.Aon9: chunk = DebugLevel9ShaderChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Priv: break; case ChunkType.Libf: chunk = DebugLibfChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Libh: chunk = DebugLibHeaderChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Lfs0: chunk = DebugLibraryParameterSignatureChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Fx10: chunk = DebugEffectChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Ctab: chunk = DebugCtabChunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Cli4: chunk = DebugCli4Chunk.Parse(chunkContentReader, chunkSize); break; case ChunkType.Fxlc: chunk = DebugFxlcChunk.Parse(chunkContentReader, chunkSize, container); break; //default: // throw new ParseException("Invalid chunk type: " + chunkType); } if (chunk == null) { chunkReader.ReadBytes("UnknownChunk", (int)chunkSize); return(null); } chunk.Container = container; chunk.FourCc = fourCc; chunk.ChunkSize = chunkSize; chunk.ChunkType = chunkType; return(chunk); }