diff --git a/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs b/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs new file mode 100644 index 000000000..d3d72755b --- /dev/null +++ b/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs @@ -0,0 +1,81 @@ +// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; + +using ICSharpCode.Decompiler.Metadata; + +namespace ILSpy.Metadata.CorTables +{ + /// + /// View of the DeclSecurity table — declarative security attributes (CAS-era + /// [SecurityPermission(...)]) attached to assemblies, types, or methods. The + /// PermissionSet blob holds a serialised XML / binary permission descriptor. + /// + public sealed class DeclSecurityTableTreeNode : MetadataTableTreeNode + { + public DeclSecurityTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.DeclSecurity, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + foreach (var row in metadataFile.Metadata.DeclarativeSecurityAttributes) + list.Add(new DeclSecurityEntry(metadataFile, row)); + return list; + } + + public sealed class DeclSecurityEntry + { + readonly MetadataFile metadataFile; + readonly DeclarativeSecurityAttributeHandle handle; + readonly DeclarativeSecurityAttribute declSecAttr; + + public int RID => MetadataTokens.GetRowNumber(handle); + + [ColumnInfo("X8")] + public int Token => MetadataTokens.GetToken(handle); + + [ColumnInfo("X8")] + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.DeclSecurity) + + metadataFile.Metadata.GetTableRowSize(TableIndex.DeclSecurity) * (RID - 1); + + [ColumnInfo("X8", Kind = ColumnKind.Token)] + public int Parent => MetadataTokens.GetToken(declSecAttr.Parent); + + [ColumnInfo("X8")] + public DeclarativeSecurityAction Action => declSecAttr.Action; + + [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] + public int PermissionSet => MetadataTokens.GetHeapOffset(declSecAttr.PermissionSet); + + public DeclSecurityEntry(MetadataFile metadataFile, DeclarativeSecurityAttributeHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + declSecAttr = metadataFile.Metadata.GetDeclarativeSecurityAttribute(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/FileTableTreeNode.cs b/ILSpy/Metadata/CorTables/FileTableTreeNode.cs new file mode 100644 index 000000000..ea496b45b --- /dev/null +++ b/ILSpy/Metadata/CorTables/FileTableTreeNode.cs @@ -0,0 +1,78 @@ +// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; + +using ICSharpCode.Decompiler.Metadata; + +namespace ILSpy.Metadata.CorTables +{ + /// + /// View of the File table — multi-module assemblies list their constituent .netmodule + /// files here. Vanishingly rare in modern .NET; nearly every assembly is single-file. + /// + public sealed class FileTableTreeNode : MetadataTableTreeNode + { + public FileTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.File, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + foreach (var row in metadataFile.Metadata.AssemblyFiles) + list.Add(new FileEntry(metadataFile, row)); + return list; + } + + public sealed class FileEntry + { + readonly MetadataFile metadataFile; + readonly AssemblyFileHandle handle; + readonly AssemblyFile assemblyFile; + + public int RID => MetadataTokens.GetRowNumber(handle); + + [ColumnInfo("X8")] + public int Token => MetadataTokens.GetToken(handle); + + [ColumnInfo("X8")] + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.File) + + metadataFile.Metadata.GetTableRowSize(TableIndex.File) * (RID - 1); + + [ColumnInfo("X8")] + public int Attributes => assemblyFile.ContainsMetadata ? 1 : 0; + + public string Name => metadataFile.Metadata.GetString(assemblyFile.Name); + + [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] + public int HashValue => MetadataTokens.GetHeapOffset(assemblyFile.HashValue); + + public FileEntry(MetadataFile metadataFile, AssemblyFileHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + assemblyFile = metadataFile.Metadata.GetAssemblyFile(handle); + } + } + } +} diff --git a/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs b/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs new file mode 100644 index 000000000..6f7c46ade --- /dev/null +++ b/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs @@ -0,0 +1,74 @@ +// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.Collections.Generic; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; + +using ICSharpCode.Decompiler.Metadata; + +namespace ILSpy.Metadata.CorTables +{ + /// + /// View of the StandAloneSig table — signatures referenced from outside their natural + /// owners: local-variable layouts for method bodies and call-site signatures for + /// calli. Each row carries a single blob signature handle. + /// + public sealed class StandAloneSigTableTreeNode : MetadataTableTreeNode + { + public StandAloneSigTableTreeNode(MetadataFile metadataFile) + : base(TableIndex.StandAloneSig, metadataFile) + { + } + + protected override IReadOnlyList LoadTable() + { + var list = new List(); + for (int row = 1; row <= metadataFile.Metadata.GetTableRowCount(TableIndex.StandAloneSig); row++) + list.Add(new StandAloneSigEntry(metadataFile, MetadataTokens.StandaloneSignatureHandle(row))); + return list; + } + + public sealed class StandAloneSigEntry + { + readonly MetadataFile metadataFile; + readonly StandaloneSignatureHandle handle; + readonly StandaloneSignature standaloneSig; + + public int RID => MetadataTokens.GetRowNumber(handle); + + [ColumnInfo("X8")] + public int Token => MetadataTokens.GetToken(handle); + + [ColumnInfo("X8")] + public int Offset => metadataFile.MetadataOffset + + metadataFile.Metadata.GetTableMetadataOffset(TableIndex.StandAloneSig) + + metadataFile.Metadata.GetTableRowSize(TableIndex.StandAloneSig) * (RID - 1); + + [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] + public int Signature => MetadataTokens.GetHeapOffset(standaloneSig.Signature); + + public StandAloneSigEntry(MetadataFile metadataFile, StandaloneSignatureHandle handle) + { + this.metadataFile = metadataFile; + this.handle = handle; + standaloneSig = metadataFile.Metadata.GetStandaloneSignature(handle); + } + } + } +} diff --git a/ILSpy/Metadata/MetadataTablesTreeNode.cs b/ILSpy/Metadata/MetadataTablesTreeNode.cs index 542ced37d..85c9d676b 100644 --- a/ILSpy/Metadata/MetadataTablesTreeNode.cs +++ b/ILSpy/Metadata/MetadataTablesTreeNode.cs @@ -94,6 +94,9 @@ namespace ILSpy.Metadata TableIndex.GenericParam => new GenericParamTableTreeNode(metadataFile), TableIndex.MethodSpec => new MethodSpecTableTreeNode(metadataFile), TableIndex.GenericParamConstraint => new GenericParamConstraintTableTreeNode(metadataFile), + TableIndex.StandAloneSig => new StandAloneSigTableTreeNode(metadataFile), + TableIndex.DeclSecurity => new DeclSecurityTableTreeNode(metadataFile), + TableIndex.File => new FileTableTreeNode(metadataFile), _ => new UnsupportedMetadataTableTreeNode(table, metadataFile), }; }