From dafe4865a26206d0c498b3bb9b34823611985457 Mon Sep 17 00:00:00 2001 From: wwh1004 Date: Thu, 24 Mar 2022 14:52:40 +0800 Subject: [PATCH] Improve the error output that occurs when saving the module (#447) * Improve the error output that occurs when saving the module * Update * rollback only one '.' changes * rollback deleted MethodBodyWriter constructors * change internal errorContext to private * fix MetadataErrorContext.Source overwritten --- .../Pdb/Portable/ImportScopeBlobWriter.cs | 6 +- .../Portable/LocalConstantSigBlobWriter.cs | 6 +- .../PortablePdbCustomDebugInfoWriter.cs | 4 +- src/DotNet/Writer/IWriterError.cs | 16 ++++ src/DotNet/Writer/MarshalBlobWriter.cs | 2 +- src/DotNet/Writer/Metadata.cs | 82 +++++++++++++------ src/DotNet/Writer/MetadataErrorContext.cs | 72 ++++++++++++++++ src/DotNet/Writer/MethodBodyWriter.cs | 17 ++-- src/DotNet/Writer/NormalMetadata.cs | 16 ++-- src/DotNet/Writer/PreserveTokensMetadata.cs | 20 ++--- 10 files changed, 175 insertions(+), 66 deletions(-) create mode 100644 src/DotNet/Writer/MetadataErrorContext.cs diff --git a/src/DotNet/Pdb/Portable/ImportScopeBlobWriter.cs b/src/DotNet/Pdb/Portable/ImportScopeBlobWriter.cs index 29c30d2d2..eac5468e2 100644 --- a/src/DotNet/Pdb/Portable/ImportScopeBlobWriter.cs +++ b/src/DotNet/Pdb/Portable/ImportScopeBlobWriter.cs @@ -36,7 +36,7 @@ void Write(DataWriter writer, IList imports) { for (int i = 0; i < count; i++) { var import = imports[i]; if (!ImportDefinitionKindUtils.ToImportDefinitionKind(import.Kind, out uint rawKind)) { - helper.Error("Unknown import definition kind: " + import.Kind.ToString()); + helper.Error2("Unknown import definition kind: {0}.", import.Kind); return; } writer.WriteCompressedUInt32(rawKind); @@ -94,7 +94,7 @@ void Write(DataWriter writer, IList imports) { break; default: - helper.Error("Unknown import definition kind: " + import.Kind.ToString()); + helper.Error2("Unknown import definition kind: {0}.", import.Kind); return; } } @@ -108,7 +108,7 @@ uint GetTypeDefOrRefEncodedToken(ITypeDefOrRef tdr) { var token = systemMetadata.GetToken(tdr); if (MD.CodedToken.TypeDefOrRef.Encode(token, out uint codedToken)) return codedToken; - helper.Error($"Could not encode token 0x{token.Raw:X8}"); + helper.Error2("Could not encode token 0x{0:X8}.", token.Raw); return 0; } } diff --git a/src/DotNet/Pdb/Portable/LocalConstantSigBlobWriter.cs b/src/DotNet/Pdb/Portable/LocalConstantSigBlobWriter.cs index 3fd0816e9..e39bd502a 100644 --- a/src/DotNet/Pdb/Portable/LocalConstantSigBlobWriter.cs +++ b/src/DotNet/Pdb/Portable/LocalConstantSigBlobWriter.cs @@ -79,7 +79,7 @@ void Write(DataWriter writer, TypeSig type, object value) { var tdr = ((ValueTypeSig)type).TypeDefOrRef; var td = tdr.ResolveTypeDef(); if (td is null) - helper.Error($"Couldn't resolve type 0x{tdr?.MDToken.Raw ?? 0:X8}"); + helper.Error2("Couldn't resolve type 0x{0:X8}.", tdr?.MDToken.Raw ?? 0); else if (td.IsEnum) { var underlyingType = td.GetEnumUnderlyingType().RemovePinnedAndModifiers(); switch (underlyingType.GetElementType()) { @@ -135,7 +135,7 @@ void Write(DataWriter writer, TypeSig type, object value) { if (value is byte[]) writer.WriteBytes((byte[])value); else if (value is not null) { - helper.Error("Unsupported constant: " + value.GetType().FullName); + helper.Error2("Unsupported constant: {0}.", value.GetType().FullName); return; } } @@ -176,7 +176,7 @@ void Write(DataWriter writer, TypeSig type, object value) { case ElementType.Sentinel: case ElementType.Pinned: default: - helper.Error("Unsupported element type in LocalConstant sig blob: " + et.ToString()); + helper.Error2("Unsupported element type in LocalConstant sig blob: {0}.", et); return; } } diff --git a/src/DotNet/Pdb/Portable/PortablePdbCustomDebugInfoWriter.cs b/src/DotNet/Pdb/Portable/PortablePdbCustomDebugInfoWriter.cs index 328382c7d..0729c602e 100644 --- a/src/DotNet/Pdb/Portable/PortablePdbCustomDebugInfoWriter.cs +++ b/src/DotNet/Pdb/Portable/PortablePdbCustomDebugInfoWriter.cs @@ -106,7 +106,7 @@ void WriteUTF8Z(string s) { void WriteStateMachineHoistedLocalScopes(PdbStateMachineHoistedLocalScopesCustomDebugInfo cdi) { if (!methodContext.HasBody) { - helper.Error("Method has no body, can't write custom debug info: " + cdi.Kind); + helper.Error2("Method has no body, can't write custom debug info: {0}.", cdi.Kind); return; } var cdiScopes = cdi.Scopes; @@ -222,7 +222,7 @@ void WriteSourceLink(PdbSourceLinkCustomDebugInfo cdi) { void WriteAsyncMethodSteppingInformation(PdbAsyncMethodCustomDebugInfo cdi) { if (!methodContext.HasBody) { - helper.Error("Method has no body, can't write custom debug info: " + cdi.Kind); + helper.Error2("Method has no body, can't write custom debug info: {0}.", cdi.Kind); return; } diff --git a/src/DotNet/Writer/IWriterError.cs b/src/DotNet/Writer/IWriterError.cs index 8575b4fea..c6e3005ec 100644 --- a/src/DotNet/Writer/IWriterError.cs +++ b/src/DotNet/Writer/IWriterError.cs @@ -27,4 +27,20 @@ public interface IWriterError2 : IWriterError { /// Optional message arguments void Error(string message, params object[] args); } + + static partial class Extensions { + /// + /// Called when an error is detected (eg. a null pointer or other invalid value). The error + /// can be ignored but the written data won't be valid. + /// + /// The instance of + /// Error message + /// Optional message arguments + internal static void Error2(this IWriterError helper, string message, params object[] args) { + if (helper is IWriterError2 helper2) + helper2.Error(message, args); + else + helper.Error(string.Format(message, args)); + } + } } diff --git a/src/DotNet/Writer/MarshalBlobWriter.cs b/src/DotNet/Writer/MarshalBlobWriter.cs index 550c0dcab..df5ead840 100644 --- a/src/DotNet/Writer/MarshalBlobWriter.cs +++ b/src/DotNet/Writer/MarshalBlobWriter.cs @@ -128,7 +128,7 @@ byte[] Write(MarshalType marshalType) { bool UpdateCanWrite(bool isValid, string field, ref bool canWriteMore) { if (!canWriteMore) { if (isValid) - helper.Error($"MarshalType field {field} is valid even though a previous field was invalid"); + helper.Error2("MarshalType field {0} is valid even though a previous field was invalid.", field); return canWriteMore; } diff --git a/src/DotNet/Writer/Metadata.cs b/src/DotNet/Writer/Metadata.cs index 15fdd4092..df93b83e1 100644 --- a/src/DotNet/Writer/Metadata.cs +++ b/src/DotNet/Writer/Metadata.cs @@ -445,6 +445,7 @@ public abstract class Metadata : IReuseChunk, ISignatureWriterHelper, ITokenProv RVA rva; readonly MetadataOptions options; ILogger logger; + readonly MetadataErrorContext errorContext; readonly NormalMetadata debugMetadata; readonly bool isStandaloneDebugMetadata; internal readonly ModuleDef module; @@ -940,6 +941,8 @@ internal Metadata(ModuleDef module, UniqueChunkList constants, M blobHeap = new BlobHeap(); pdbHeap = new PdbHeap(); + errorContext = new MetadataErrorContext(); + this.isStandaloneDebugMetadata = isStandaloneDebugMetadata; switch (debugKind) { case DebugMetadataKind.None: @@ -1403,20 +1406,27 @@ public ByteArrayChunk GetInitialValueChunk(FieldDef fd) { /// /// Error message /// Optional message arguments - protected void Error(string message, params object[] args) => GetLogger().Log(this, LoggerEvent.Error, message, args); + protected void Error(string message, params object[] args) { + errorContext.Append("Error", ref message, ref args); + GetLogger().Log(this, LoggerEvent.Error, message, args); + } /// /// Called to warn of something /// /// Warning message /// Optional message arguments - protected void Warning(string message, params object[] args) => GetLogger().Log(this, LoggerEvent.Warning, message, args); + protected void Warning(string message, params object[] args) { + errorContext.Append("Warning", ref message, ref args); + GetLogger().Log(this, LoggerEvent.Warning, message, args); + } /// /// Raises /// /// Event protected void OnMetadataEvent(MetadataEvent evt) { + errorContext.Event = evt; RaiseProgress(evt, 0); MetadataEvent?.Invoke(this, new MetadataWriterEventArgs(this, evt)); } @@ -1572,6 +1582,8 @@ void InitializeTypeDefsAndMemberDefs() { int notifyAfter = numTypes / numNotifyEvents; foreach (var type in allTypeDefs) { + using var _ = errorContext.SetSource(type); + if (typeNum++ == notifyAfter && notifyNum < numNotifyEvents) { RaiseProgress(Writer.MetadataEvent.MemberDefRidsAllocated, (double)typeNum / numTypes); notifyNum++; @@ -1597,9 +1609,10 @@ void InitializeTypeDefsAndMemberDefs() { for (int i = 0; i < count; i++) { var field = fields[i]; if (field is null) { - Error("Field is null. TypeDef {0} ({1:X8})", type, type.MDToken.Raw); + Error("Field is null"); continue; } + using var __ = errorContext.SetSource(field); uint rid = GetRid(field); var row = new RawFieldRow((ushort)field.Attributes, stringsHeap.Add(field.Name), GetSignature(field.Signature)); tablesHeap.FieldTable[rid] = row; @@ -1615,9 +1628,10 @@ void InitializeTypeDefsAndMemberDefs() { for (int i = 0; i < count; i++) { var method = methods[i]; if (method is null) { - Error("Method is null. TypeDef {0} ({1:X8})", type, type.MDToken.Raw); + Error("Method is null"); continue; } + using var __ = errorContext.SetSource(method); if (method.ExportInfo is not null) ExportedMethods.Add(method); uint rid = GetRid(method); @@ -1633,7 +1647,7 @@ void InitializeTypeDefsAndMemberDefs() { for (int j = 0; j < count2; j++) { var pd = paramDefs[j]; if (pd is null) { - Error("Param is null. Method {0} ({1:X8})", method, method.MDToken.Raw); + Error("Param is null"); continue; } uint pdRid = GetRid(pd); @@ -1649,9 +1663,10 @@ void InitializeTypeDefsAndMemberDefs() { for (int i = 0; i < count; i++) { var evt = events[i]; if (evt is null) { - Error("Event is null. TypeDef {0} ({1:X8})", type, type.MDToken.Raw); + Error("Event is null"); continue; } + using var __ = errorContext.SetSource(evt); uint rid = GetRid(evt); var row = new RawEventRow((ushort)evt.Attributes, stringsHeap.Add(evt.Name), AddTypeDefOrRef(evt.EventType)); tablesHeap.EventTable[rid] = row; @@ -1663,9 +1678,10 @@ void InitializeTypeDefsAndMemberDefs() { for (int i = 0; i < count; i++) { var prop = properties[i]; if (prop is null) { - Error("Property is null. TypeDef {0} ({1:X8})", type, type.MDToken.Raw); + Error("Property is null"); continue; } + using var __ = errorContext.SetSource(prop); uint rid = GetRid(prop); var row = new RawPropertyRow((ushort)prop.Attributes, stringsHeap.Add(prop.Name), GetSignature(prop.Type)); tablesHeap.PropertyTable[rid] = row; @@ -1689,6 +1705,8 @@ void WriteTypeDefAndMemberDefCustomAttributesAndCustomDebugInfos() { uint rid; foreach (var type in allTypeDefs) { + using var _ = errorContext.SetSource(type); + if (typeNum++ == notifyAfter && notifyNum < numNotifyEvents) { RaiseProgress(Writer.MetadataEvent.MostTablesSorted, (double)typeNum / numTypes); notifyNum++; @@ -1722,6 +1740,7 @@ void WriteTypeDefAndMemberDefCustomAttributesAndCustomDebugInfos() { var method = methods[i]; if (method is null) continue; + using var __ = errorContext.SetSource(method); if (method.HasCustomAttributes) { rid = GetRid(method); AddCustomAttributes(Table.Method, rid, method); @@ -1775,6 +1794,7 @@ void InitializeVTableFixups() { if (fixups is null || fixups.VTables.Count == 0) return; + using var _ = errorContext.SetSource("vtable fixups"); foreach (var vtable in fixups) { if (vtable is null) { Error("VTable is null"); @@ -1789,6 +1809,7 @@ void InitializeVTableFixups() { } void AddExportedTypes() { + using var _ = errorContext.SetSource("exported types"); var exportedTypes = module.ExportedTypes; int count = exportedTypes.Count; for (int i = 0; i < count; i++) @@ -1800,6 +1821,7 @@ void AddExportedTypes() { /// a , it will have already been added. /// void InitializeEntryPoint() { + using var _ = errorContext.SetSource("entry point"); if (module.ManagedEntryPoint is FileDef epFile) AddFile(epFile); } @@ -1885,6 +1907,7 @@ void InitializeGenericParamConstraintTable() { foreach (var type in allTypeDefs) { if (type is null) continue; + using var _ = errorContext.SetSource(type); AddGenericParamConstraints(type.GenericParameters); var methods = type.Methods; int count = methods.Count; @@ -1892,6 +1915,7 @@ void InitializeGenericParamConstraintTable() { var method = methods[i]; if (method is null) continue; + using var __ = errorContext.SetSource(method); AddGenericParamConstraints(method.GenericParameters); } } @@ -1975,12 +1999,16 @@ void WriteMethodBodies() { if (type is null) continue; + using var _ = errorContext.SetSource(type); + var methods = type.Methods; for (int i = 0; i < methods.Count; i++) { var method = methods[i]; if (method is null) continue; + using var __ = errorContext.SetSource(method); + if (methodNum++ == notifyAfter && notifyNum < numNotifyEvents) { RaiseProgress(Writer.MetadataEvent.BeginWriteMethodBodies, (double)methodNum / numMethods); notifyNum++; @@ -1992,7 +2020,7 @@ void WriteMethodBodies() { var cilBody = method.Body; if (cilBody is not null) { if (!(cilBody.Instructions.Count == 0 && cilBody.Variables.Count == 0)) { - writer.Reset(method, keepMaxStack || cilBody.KeepOldMaxStack); + writer.Reset(cilBody, keepMaxStack || cilBody.KeepOldMaxStack); writer.Write(); var origRva = method.RVA; uint origSize = cilBody.MetadataBodySize; @@ -2305,7 +2333,7 @@ protected uint AddTypeDefOrRef(ITypeDefOrRef tdr) { var token = new MDToken(tdr.MDToken.Table, AddMDTokenProvider(tdr)); if (!CodedToken.TypeDefOrRef.Encode(token, out uint encodedToken)) { - Error("Can't encode TypeDefOrRef token {0:X8}", token.Raw); + Error("Can't encode TypeDefOrRef token 0x{0:X8}.", token.Raw); encodedToken = 0; } return encodedToken; @@ -2323,7 +2351,7 @@ protected uint AddResolutionScope(IResolutionScope rs) { var token = new MDToken(rs.MDToken.Table, AddMDTokenProvider(rs)); if (!CodedToken.ResolutionScope.Encode(token, out uint encodedToken)) { - Error("Can't encode ResolutionScope token {0:X8}", token.Raw); + Error("Can't encode ResolutionScope token 0x{0:X8}.", token.Raw); encodedToken = 0; } return encodedToken; @@ -2342,7 +2370,7 @@ protected uint AddMethodDefOrRef(IMethodDefOrRef mdr) { var token = new MDToken(mdr.MDToken.Table, AddMDTokenProvider(mdr)); if (!CodedToken.MethodDefOrRef.Encode(token, out uint encodedToken)) { - Error("Can't encode MethodDefOrRef token {0:X8}", token.Raw); + Error("Can't encode MethodDefOrRef token 0x{0:X8}.", token.Raw); encodedToken = 0; } return encodedToken; @@ -2361,7 +2389,7 @@ protected uint AddMemberRefParent(IMemberRefParent parent) { var token = new MDToken(parent.MDToken.Table, AddMDTokenProvider(parent)); if (!CodedToken.MemberRefParent.Encode(token, out uint encodedToken)) { - Error("Can't encode MemberRefParent token {0:X8}", token.Raw); + Error("Can't encode MemberRefParent token 0x{0:X8}.", token.Raw); encodedToken = 0; } return encodedToken; @@ -2380,7 +2408,7 @@ protected uint AddImplementation(IImplementation impl) { var token = new MDToken(impl.MDToken.Table, AddMDTokenProvider(impl)); if (!CodedToken.Implementation.Encode(token, out uint encodedToken)) { - Error("Can't encode Implementation token {0:X8}", token.Raw); + Error("Can't encode Implementation token 0x{0:X8}.", token.Raw); encodedToken = 0; } return encodedToken; @@ -2399,7 +2427,7 @@ protected uint AddCustomAttributeType(ICustomAttributeType cat) { var token = new MDToken(cat.MDToken.Table, AddMDTokenProvider(cat)); if (!CodedToken.CustomAttributeType.Encode(token, out uint encodedToken)) { - Error("Can't encode CustomAttributeType token {0:X8}", token.Raw); + Error("Can't encode CustomAttributeType token 0x{0:X8}.", token.Raw); encodedToken = 0; } return encodedToken; @@ -2432,7 +2460,7 @@ protected uint AddModule(ModuleDef module) { return 0; } if (this.module != module) - Error("Module {0} must be referenced with a ModuleRef, not a ModuleDef", module); + Error("Module '{0}' must be referenced with a ModuleRef, not a ModuleDef.", module); if (moduleDefInfos.TryGetRid(module, out uint rid)) return rid; var row = new RawModuleRow(module.Generation, @@ -2558,7 +2586,7 @@ protected void AddGenericParam(MDToken owner, GenericParam gp) { return; } if (!CodedToken.TypeOrMethodDef.Encode(owner, out uint encodedOwner)) { - Error("Can't encode TypeOrMethodDef token {0:X8}", owner.Raw); + Error("Can't encode TypeOrMethodDef token 0x{0:X8}.", owner.Raw); encodedOwner = 0; } var row = new RawGenericParamRow(gp.Number, @@ -2648,7 +2676,7 @@ protected void AddFieldMarshal(MDToken parent, IHasFieldMarshal hfm) { return; var fieldMarshal = hfm.MarshalType; if (!CodedToken.HasFieldMarshal.Encode(parent, out uint encodedParent)) { - Error("Can't encode HasFieldMarshal token {0:X8}", parent.Raw); + Error("Can't encode HasFieldMarshal token 0x{0:X8}.", parent.Raw); encodedParent = 0; } var row = new RawFieldMarshalRow(encodedParent, @@ -2674,7 +2702,7 @@ protected void AddFieldRVA(FieldDef field) { return; var ivBytes = field.InitialValue; if (!VerifyFieldSize(field, ivBytes.Length)) - Error("Field {0} ({1:X8}) initial value size != size of field type", field, field.MDToken.Raw); + Error("Field '{0}' (0x{1:X8}) initial value size != size of field type.", field, field.MDToken.Raw); uint rid = GetRid(field); var iv = constants.Add(new ByteArrayChunk(ivBytes), ModuleWriterBase.DEFAULT_CONSTANTS_ALIGNMENT); fieldToInitialValue[field] = iv; @@ -2702,7 +2730,7 @@ protected void AddImplMap(MDToken parent, IMemberForwarded mf) { return; var implMap = mf.ImplMap; if (!CodedToken.MemberForwarded.Encode(parent, out uint encodedParent)) { - Error("Can't encode MemberForwarded token {0:X8}", parent.Raw); + Error("Can't encode MemberForwarded token 0x{0:X8}.", parent.Raw); encodedParent = 0; } var row = new RawImplMapRow((ushort)implMap.Attributes, @@ -2722,7 +2750,7 @@ protected void AddConstant(MDToken parent, IHasConstant hc) { return; var constant = hc.Constant; if (!CodedToken.HasConstant.Encode(parent, out uint encodedParent)) { - Error("Can't encode HasConstant token {0:X8}", parent.Raw); + Error("Can't encode HasConstant token 0x{0:X8}.", parent.Raw); encodedParent = 0; } var row = new RawConstantRow((byte)constant.Type, 0, @@ -2815,7 +2843,7 @@ protected void AddDeclSecurities(MDToken parent, IList declSecurit if (declSecurities is null) return; if (!CodedToken.HasDeclSecurity.Encode(parent, out uint encodedParent)) { - Error("Can't encode HasDeclSecurity token {0:X8}", parent.Raw); + Error("Can't encode HasDeclSecurity token 0x{0:X8}.", parent.Raw); encodedParent = 0; } var bwctx = AllocBinaryWriterContext(); @@ -2884,7 +2912,7 @@ void AddMethodSemantics(MDToken owner, MethodDef method, MethodSemanticsAttribut if (methodRid == 0) return; if (!CodedToken.HasSemantic.Encode(owner, out uint encodedOwner)) { - Error("Can't encode HasSemantic token {0:X8}", owner.Raw); + Error("Can't encode HasSemantic token 0x{0:X8}.", owner.Raw); encodedOwner = 0; } var row = new RawMethodSemanticsRow((ushort)flags, methodRid, encodedOwner); @@ -2895,7 +2923,7 @@ void AddMethodImpls(MethodDef method, IList overrides) { if (overrides is null) return; if (method.DeclaringType is null) { - Error("Method declaring type is null. Method {0} ({1:X8})", method, method.MDToken.Raw); + Error("Method declaring type is null"); return; } if (overrides.Count != 0) { @@ -2954,7 +2982,7 @@ void AddResource(Resource resource) { if (resource is null) Error("Resource is null"); else - Error("Invalid resource type: {0}", resource.GetType()); + Error("Invalid resource type: '{0}'.", resource.GetType()); } uint AddEmbeddedResource(EmbeddedResource er) { @@ -3132,7 +3160,7 @@ void AddCustomAttribute(MDToken token, CustomAttribute ca) { return; } if (!CodedToken.HasCustomAttribute.Encode(token, out uint encodedToken)) { - Error("Can't encode HasCustomAttribute token {0:X8}", token.Raw); + Error("Can't encode HasCustomAttribute token 0x{0:X8}.", token.Raw); encodedToken = 0; } var bwctx = AllocBinaryWriterContext(); @@ -3315,7 +3343,7 @@ void AddCustomDebugInformationCore(SerializerMethodContext serializerMethodConte var token = new MDToken(table, rid); if (!CodedToken.HasCustomDebugInformation.Encode(token, out uint encodedToken)) { - Error("Couldn't encode HasCustomDebugInformation token {0:X8}", token.Raw); + Error("Couldn't encode HasCustomDebugInformation token 0x{0:X8}.", token.Raw); return; } @@ -3371,7 +3399,7 @@ void AddCustomDebugInformation(SerializerMethodContext serializerMethodContext, break; default: - Error("Unknown custom debug info {0}", cdi.Kind.ToString()); + Error("Unknown custom debug info {0}.", cdi.Kind); break; } } diff --git a/src/DotNet/Writer/MetadataErrorContext.cs b/src/DotNet/Writer/MetadataErrorContext.cs new file mode 100644 index 000000000..dee31d720 --- /dev/null +++ b/src/DotNet/Writer/MetadataErrorContext.cs @@ -0,0 +1,72 @@ +// dnlib: See LICENSE.txt for more info + +using System; +using System.Text; + +namespace dnlib.DotNet.Writer { + sealed class MetadataErrorContext { + sealed class ErrorSource : IDisposable { + MetadataErrorContext context; + readonly ErrorSource originalValue; + + public object Value { get; } + + public ErrorSource(MetadataErrorContext context, object value) { + this.context = context; + Value = value; + originalValue = context.source; + } + + public void Dispose() { + if (context is null) + return; + context.source = originalValue; + context = null; + } + } + + ErrorSource source; + + public MetadataEvent Event { get; set; } + + public IDisposable SetSource(object source) => this.source = new ErrorSource(this, source); + + public void Append(string errorLevel, ref string message, ref object[] args) { + int count = 1; + var stringSource = source?.Value as string; + var tokenSource = source?.Value as IMDTokenProvider; + if (tokenSource is not null) + count += 2; + int ctxArgIndex = args.Length; + + var newMessage = new StringBuilder(message); + var newArgs = new object[args.Length + count]; + Array.Copy(args, 0, newArgs, 0, args.Length); + + if (newMessage.Length != 0 && newMessage[newMessage.Length - 1] != '.') + newMessage.Append('.'); + newMessage.AppendFormat(" {0} occurred after metadata event {{{1}}}", errorLevel, ctxArgIndex); + newArgs[ctxArgIndex] = Event; + + if (tokenSource is not null) { + string sourceType = tokenSource switch { + TypeDef => "type", + FieldDef => "field", + MethodDef => "method", + EventDef => "event", + PropertyDef => "property", + _ => "???" + }; + newMessage.AppendFormat(" during writing {0} '{{{1}}}' (0x{{{2}:X8}})", sourceType, ctxArgIndex + 1, ctxArgIndex + 2); + newArgs[ctxArgIndex + 1] = tokenSource; + newArgs[ctxArgIndex + 2] = tokenSource.MDToken.Raw; + } + else if (stringSource is not null) { + newMessage.AppendFormat(" during writing {0}", stringSource); + } + + message = newMessage.Append('.').ToString(); + args = newArgs; + } + } +} diff --git a/src/DotNet/Writer/MethodBodyWriter.cs b/src/DotNet/Writer/MethodBodyWriter.cs index dcdafb88e..0fad93f32 100644 --- a/src/DotNet/Writer/MethodBodyWriter.cs +++ b/src/DotNet/Writer/MethodBodyWriter.cs @@ -31,7 +31,6 @@ public interface ITokenProvider : IWriterError { /// public sealed class MethodBodyWriter : MethodBodyWriterBase { readonly ITokenProvider helper; - MethodDef method; CilBody cilBody; bool keepMaxStack; uint codeSize; @@ -77,7 +76,7 @@ public MethodBodyWriter(ITokenProvider helper, MethodDef method) public MethodBodyWriter(ITokenProvider helper, MethodDef method, bool keepMaxStack) : base(method.Body.Instructions, method.Body.ExceptionHandlers) { this.helper = helper; - this.method = method; + cilBody = method.Body; this.keepMaxStack = keepMaxStack; } @@ -108,16 +107,15 @@ internal MethodBodyWriter(ITokenProvider helper) { this.helper = helper; } - internal void Reset(MethodDef method, bool keepMaxStack) { - this.method = method; + internal void Reset(CilBody cilBody, bool keepMaxStack) { + Reset(cilBody.Instructions, cilBody.ExceptionHandlers); + this.cilBody = cilBody; this.keepMaxStack = keepMaxStack; - cilBody = method.Body; codeSize = 0; maxStack = 0; code = null; extraSections = null; localVarSigTok = 0; - Reset(cilBody.Instructions, cilBody.ExceptionHandlers); } /// @@ -324,12 +322,7 @@ byte[] WriteSmallExceptionClauses() { } /// - protected override void ErrorImpl(string message) { - if (method is not null && helper is IWriterError2 writerError2) - writerError2.Error(message + " At method {0} ({1:X8}).", method, method.MDToken.Raw); - else - helper.Error(message); - } + protected override void ErrorImpl(string message) => helper.Error(message); /// protected override void WriteInlineField(ref ArrayWriter writer, Instruction instr) => writer.WriteUInt32(helper.GetToken(instr.Operand).Raw); diff --git a/src/DotNet/Writer/NormalMetadata.cs b/src/DotNet/Writer/NormalMetadata.cs index 13ef316d0..1e8443cbb 100644 --- a/src/DotNet/Writer/NormalMetadata.cs +++ b/src/DotNet/Writer/NormalMetadata.cs @@ -149,7 +149,7 @@ public override uint GetRid(TypeDef td) { if (td is null) Error("TypeDef is null"); else - Error("TypeDef {0} ({1:X8}) is not defined in this module ({2}). A type was removed that is still referenced by this module.", td, td.MDToken.Raw, module); + Error("TypeDef '{0}' (0x{1:X8}) is not defined in this module '{2}'. A type was removed that is still referenced by this module.", td, td.MDToken.Raw, module); return 0; } @@ -160,7 +160,7 @@ public override uint GetRid(FieldDef fd) { if (fd is null) Error("Field is null"); else - Error("Field {0} ({1:X8}) is not defined in this module ({2}). A field was removed that is still referenced by this module.", fd, fd.MDToken.Raw, module); + Error("Field '{0}' (0x{1:X8}) is not defined in this module '{2}'. A field was removed that is still referenced by this module.", fd, fd.MDToken.Raw, module); return 0; } @@ -171,7 +171,7 @@ public override uint GetRid(MethodDef md) { if (md is null) Error("Method is null"); else - Error("Method {0} ({1:X8}) is not defined in this module ({2}). A method was removed that is still referenced by this module.", md, md.MDToken.Raw, module); + Error("Method '{0}' (0x{1:X8}) is not defined in this module '{2}'. A method was removed that is still referenced by this module.", md, md.MDToken.Raw, module); return 0; } @@ -182,7 +182,7 @@ public override uint GetRid(ParamDef pd) { if (pd is null) Error("Param is null"); else - Error("Param {0} ({1:X8}) is not defined in this module ({2}). A parameter was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); + Error("Param '{0}' (0x{1:X8}) is not defined in this module '{2}'. A parameter was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); return 0; } @@ -205,7 +205,7 @@ public override uint GetRid(EventDef ed) { if (ed is null) Error("Event is null"); else - Error("Event {0} ({1:X8}) is not defined in this module ({2}). An event was removed that is still referenced by this module.", ed, ed.MDToken.Raw, module); + Error("Event '{0}' (0x{1:X8}) is not defined in this module '{2}'. An event was removed that is still referenced by this module.", ed, ed.MDToken.Raw, module); return 0; } @@ -216,7 +216,7 @@ public override uint GetRid(PropertyDef pd) { if (pd is null) Error("Property is null"); else - Error("Property {0} ({1:X8}) is not defined in this module ({2}). A property was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); + Error("Property '{0}' (0x{1:X8}) is not defined in this module '{2}'. A property was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); return 0; } @@ -240,7 +240,7 @@ protected override uint AddTypeRef(TypeRef tr) { } if (typeRefInfos.TryGetRid(tr, out uint rid)) { if (rid == 0) - Error("TypeRef {0:X8} has an infinite ResolutionScope loop", tr.MDToken.Raw); + Error("TypeRef 0x{0:X8} has an infinite ResolutionScope loop.", tr.MDToken.Raw); return rid; } typeRefInfos.Add(tr, 0); // Prevent inf recursion @@ -262,7 +262,7 @@ protected override uint AddTypeSpec(TypeSpec ts) { } if (typeSpecInfos.TryGetRid(ts, out uint rid)) { if (rid == 0) - Error("TypeSpec {0:X8} has an infinite TypeSig loop", ts.MDToken.Raw); + Error("TypeSpec 0x{0:X8} has an infinite TypeSig loop.", ts.MDToken.Raw); return rid; } typeSpecInfos.Add(ts, 0); // Prevent inf recursion diff --git a/src/DotNet/Writer/PreserveTokensMetadata.cs b/src/DotNet/Writer/PreserveTokensMetadata.cs index db4a71dc7..376adaf89 100644 --- a/src/DotNet/Writer/PreserveTokensMetadata.cs +++ b/src/DotNet/Writer/PreserveTokensMetadata.cs @@ -210,7 +210,7 @@ public override uint GetRid(TypeDef td) { } if (typeToRid.TryGetValue(td, out uint rid)) return rid; - Error("TypeDef {0} ({1:X8}) is not defined in this module ({2}). A type was removed that is still referenced by this module.", td, td.MDToken.Raw, module); + Error("TypeDef '{0}' (0x{1:X8}) is not defined in this module '{2}'. A type was removed that is still referenced by this module.", td, td.MDToken.Raw, module); return 0; } @@ -221,7 +221,7 @@ public override uint GetRid(FieldDef fd) { if (fd is null) Error("Field is null"); else - Error("Field {0} ({1:X8}) is not defined in this module ({2}). A field was removed that is still referenced by this module.", fd, fd.MDToken.Raw, module); + Error("Field '{0}' (0x{1:X8}) is not defined in this module '{2}'. A field was removed that is still referenced by this module.", fd, fd.MDToken.Raw, module); return 0; } @@ -232,7 +232,7 @@ public override uint GetRid(MethodDef md) { if (md is null) Error("Method is null"); else - Error("Method {0} ({1:X8}) is not defined in this module ({2}). A method was removed that is still referenced by this module.", md, md.MDToken.Raw, module); + Error("Method '{0}' (0x{1:X8}) is not defined in this module '{2}'. A method was removed that is still referenced by this module.", md, md.MDToken.Raw, module); return 0; } @@ -243,7 +243,7 @@ public override uint GetRid(ParamDef pd) { if (pd is null) Error("Param is null"); else - Error("Param {0} ({1:X8}) is not defined in this module ({2}). A parameter was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); + Error("Param '{0}' (0x{1:X8}) is not defined in this module '{2}'. A parameter was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); return 0; } @@ -266,7 +266,7 @@ public override uint GetRid(EventDef ed) { if (ed is null) Error("Event is null"); else - Error("Event {0} ({1:X8}) is not defined in this module ({2}). An event was removed that is still referenced by this module.", ed, ed.MDToken.Raw, module); + Error("Event '{0}' (0x{1:X8}) is not defined in this module '{2}'. An event was removed that is still referenced by this module.", ed, ed.MDToken.Raw, module); return 0; } @@ -277,7 +277,7 @@ public override uint GetRid(PropertyDef pd) { if (pd is null) Error("Property is null"); else - Error("Property {0} ({1:X8}) is not defined in this module ({2}). A property was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); + Error("Property '{0}' (0x{1:X8}) is not defined in this module '{2}'. A property was removed that is still referenced by this module.", pd, pd.MDToken.Raw, module); return 0; } @@ -1033,7 +1033,7 @@ protected override uint AddTypeRef(TypeRef tr) { } if (typeRefInfos.TryGetRid(tr, out uint rid)) { if (rid == 0) - Error("TypeRef {0:X8} has an infinite ResolutionScope loop", tr.MDToken.Raw); + Error("TypeRef 0x{0:X8} has an infinite ResolutionScope loop.", tr.MDToken.Raw); return rid; } typeRefInfos.Add(tr, 0); // Prevent inf recursion @@ -1062,7 +1062,7 @@ uint AddTypeSpec(TypeSpec ts, bool forceIsOld) { } if (typeSpecInfos.TryGetRid(ts, out uint rid)) { if (rid == 0) - Error("TypeSpec {0:X8} has an infinite TypeSig loop", ts.MDToken.Raw); + Error("TypeSpec 0x{0:X8} has an infinite TypeSig loop.", ts.MDToken.Raw); return rid; } typeSpecInfos.Add(ts, 0); // Prevent inf recursion @@ -1169,14 +1169,14 @@ uint AddStandAloneSig(CallingConventionSig callConvSig, uint origToken) { if (callConvTokenToSignature.TryGetValue(origToken, out uint otherSig)) { if (sig == otherSig) return MDToken.ToRID(origToken); - Warning("Could not preserve StandAloneSig token {0:X8}", origToken); + Warning("Could not preserve StandAloneSig token 0x{0:X8}", origToken); return 0; } uint rid = MDToken.ToRID(origToken); var sas = mod.ResolveStandAloneSig(rid); if (standAloneSigInfos.Exists(sas)) { - Warning("StandAloneSig {0:X8} already exists", origToken); + Warning("StandAloneSig 0x{0:X8} already exists", origToken); return 0; }