diff --git a/.gitignore b/.gitignore
index 5bf1c1e2b..8b3b163cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,6 +60,7 @@ x64/
build/
[Bb]in/
[Oo]bj/
+artifacts/
# MSTest test Results
[Tt]est[Rr]esult*/
diff --git a/AsmResolver.sln b/AsmResolver.sln
index 0cf5601e0..492017f8f 100644
--- a/AsmResolver.sln
+++ b/AsmResolver.sln
@@ -4,8 +4,14 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 17.0.31919.166
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{34A95168-A162-4F6A-803B-B6F221FE9EA6}"
+ ProjectSection(SolutionItems) = preProject
+ src\Directory.Build.props = src\Directory.Build.props
+ EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{786C1732-8C96-45DD-97BB-639C9AA7F45B}"
+ ProjectSection(SolutionItems) = preProject
+ test\Directory.Build.props = test\Directory.Build.props
+ EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsmResolver", "src\AsmResolver\AsmResolver.csproj", "{4EA3F800-1A1B-4465-931F-4E9949C3373B}"
EndProject
diff --git a/Directory.Build.props b/Directory.Build.props
index fd7226b04..a183e92e4 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,14 +1,15 @@
- Copyright © Washi 2016-2023
+ Copyright © Washi 2016-2024
https://github.com/Washi1337/AsmResolver
https://github.com/Washi1337/AsmResolver/LICENSE.md
https://github.com/Washi1337/AsmResolver
git
10
- 5.5.0
+ 5.5.1
true
+ true
diff --git a/appveyor.yml b/appveyor.yml
index 270821ada..2006831eb 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -4,7 +4,7 @@
- master
image: Visual Studio 2022
- version: 5.5.0-master-build.{build}
+ version: 5.5.1-master-build.{build}
configuration: Release
skip_commits:
@@ -18,7 +18,7 @@
verbosity: minimal
artifacts:
- - path: '**\*.nupkg'
+ - path: 'artifacts\package\release\*.nupkg'
deploy:
provider: NuGet
@@ -33,7 +33,7 @@
- development
image: Visual Studio 2022
- version: 5.5.0-dev-build.{build}
+ version: 5.5.1-dev-build.{build}
configuration: Release
skip_commits:
@@ -47,4 +47,4 @@
verbosity: minimal
artifacts:
- - path: '**\*.nupkg'
+ - path: 'artifacts\package\release\*.nupkg'
diff --git a/docs/guides/dotnet/importing.md b/docs/guides/dotnet/importing.md
index b446d9869..b5a937e3a 100644
--- a/docs/guides/dotnet/importing.md
+++ b/docs/guides/dotnet/importing.md
@@ -106,6 +106,16 @@ imported through reflection include:
is created).
- Generic parameters.
- Generic type instantiations.
+- Function pointer types (.NET 8.0+ only. TFM doesn't matter for this, the runtime used at runtime is all that matters.) (!!WARNING!! )
+
+> [!WARNING]
+> Function pointer `Type` instances lose their calling conventions unless attained with
+> `GetModified(Field/Property/Parameter)Type`. This includes `typeof`!
+> `typeof(delegate*unmanaged[Cdecl])` is the same as `typeof(delegate*managed)`.
+> `Import(Field/Method)` will also strip the calling conventions from function pointers
+> that are the types of fields or in method signatures.
+> If you need to handle this, manually set the types in the resulting
+> `IMethodDefOrRef` or `MemberReference` to the appropriate type from `ImportType`.
Instantiations of generic methods are also supported.
diff --git a/src/AsmResolver.DotNet.Dynamic/AsmResolver.DotNet.Dynamic.csproj b/src/AsmResolver.DotNet.Dynamic/AsmResolver.DotNet.Dynamic.csproj
index f6c65a741..6db621977 100644
--- a/src/AsmResolver.DotNet.Dynamic/AsmResolver.DotNet.Dynamic.csproj
+++ b/src/AsmResolver.DotNet.Dynamic/AsmResolver.DotNet.Dynamic.csproj
@@ -4,10 +4,7 @@
AsmResolver.DotNet.Dynamic
Dynamic method support for the AsmResolver executable file inspection toolsuite.
exe pe directories imports exports resources dotnet cil inspection manipulation assembly disassembly dynamic
- true
1701;1702;NU5105
- net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1
- enable
@@ -23,9 +20,9 @@
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/AsmResolver.DotNet.Dynamic/DynamicCilOperandResolver.cs b/src/AsmResolver.DotNet.Dynamic/DynamicCilOperandResolver.cs
index 8f4b202f4..4368460f8 100644
--- a/src/AsmResolver.DotNet.Dynamic/DynamicCilOperandResolver.cs
+++ b/src/AsmResolver.DotNet.Dynamic/DynamicCilOperandResolver.cs
@@ -37,7 +37,7 @@ public DynamicCilOperandResolver(SerializedModuleDefinition contextModule, CilMe
case TableIndex.TypeDef:
object? type = _tokens[(int)token.Rid];
if (type is RuntimeTypeHandle runtimeTypeHandle)
- return _importer.ImportType(Type.GetTypeFromHandle(runtimeTypeHandle));
+ return _importer.ImportType(Type.GetTypeFromHandle(runtimeTypeHandle)!);
break;
case TableIndex.Field:
diff --git a/src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs b/src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs
index 4fdc14587..0b6465aa8 100644
--- a/src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs
+++ b/src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs
@@ -84,7 +84,10 @@ private static CilMethodBody CreateDynamicMethodBody(MethodDefinition method, ob
// if the DynamicMethod code is not flushed yet into the resolver (e.g., it hasn't been invoked yet).
object? dynamicILInfo = null;
if (FieldReader.TryReadField(resolver, "m_method", out var m) && m is not null)
- FieldReader.TryReadField(m, "m_DynamicILInfo", out dynamicILInfo);
+ {
+ if (!FieldReader.TryReadField(m, "m_DynamicILInfo", out dynamicILInfo))
+ FieldReader.TryReadField(m, "_dynamicILInfo", out dynamicILInfo);
+ }
// Extract all required information to construct the body.
byte[]? code;
diff --git a/src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs b/src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs
index 27e3d27c3..909b015d6 100644
--- a/src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs
+++ b/src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs
@@ -101,7 +101,9 @@ public static object ResolveDynamicResolver(object dynamicMethodObj)
if (dynamicMethodObj.GetType().FullName == "System.Reflection.Emit.DynamicMethod")
{
- object? resolver = FieldReader.ReadField
@@ -24,9 +21,9 @@
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/AsmResolver.DotNet/Code/Cil/CilInstructionCollection.cs b/src/AsmResolver.DotNet/Code/Cil/CilInstructionCollection.cs
index 970bc7b26..60616bc07 100644
--- a/src/AsmResolver.DotNet/Code/Cil/CilInstructionCollection.cs
+++ b/src/AsmResolver.DotNet/Code/Cil/CilInstructionCollection.cs
@@ -459,7 +459,7 @@ private bool TryOptimizeVariable(CilInstruction instruction)
{
var variable = instruction.GetLocalVariable(Owner.LocalVariables);
- CilOpCode code = instruction.OpCode;
+ var code = instruction.OpCode;
object? operand = instruction.Operand;
if (instruction.IsLdloc())
@@ -470,7 +470,7 @@ private bool TryOptimizeVariable(CilInstruction instruction)
1 => (CilOpCodes.Ldloc_1, null),
2 => (CilOpCodes.Ldloc_2, null),
3 => (CilOpCodes.Ldloc_3, null),
- {} x when x >= byte.MinValue && x <= byte.MaxValue => (CilOpCodes.Ldloc_S, variable),
+ <= byte.MaxValue and >= byte.MinValue => (CilOpCodes.Ldloc_S, variable),
_ => (CilOpCodes.Ldloc, variable),
};
}
@@ -482,10 +482,15 @@ private bool TryOptimizeVariable(CilInstruction instruction)
1 => (CilOpCodes.Stloc_1, null),
2 => (CilOpCodes.Stloc_2, null),
3 => (CilOpCodes.Stloc_3, null),
- {} x when x >= byte.MinValue && x <= byte.MaxValue => (CilOpCodes.Stloc_S, variable),
+ <= byte.MaxValue and >= byte.MinValue => (CilOpCodes.Stloc_S, variable),
_ => (CilOpCodes.Stloc, variable),
};
}
+ else if (instruction.OpCode.Code == CilCode.Ldloca)
+ {
+ if (variable.Index is >= byte.MinValue and <= byte.MaxValue)
+ code = CilOpCodes.Ldloca_S;
+ }
if (code != instruction.OpCode)
{
@@ -501,7 +506,7 @@ private bool TryOptimizeArgument(CilInstruction instruction)
{
var parameter = instruction.GetParameter(Owner.Owner.Parameters);
- CilOpCode code = instruction.OpCode;
+ var code = instruction.OpCode;
object? operand = instruction.Operand;
if (instruction.IsLdarg())
@@ -512,15 +517,19 @@ private bool TryOptimizeArgument(CilInstruction instruction)
1 => (CilOpCodes.Ldarg_1, null),
2 => (CilOpCodes.Ldarg_2, null),
3 => (CilOpCodes.Ldarg_3, null),
- {} x when x >= byte.MinValue && x <= byte.MaxValue => (CilOpCodes.Ldarg_S, parameter),
+ >= byte.MinValue and <= byte.MaxValue => (CilOpCodes.Ldarg_S, parameter),
_ => (CilOpCodes.Ldarg, parameter),
};
}
else if (instruction.IsStarg())
{
- code = parameter.MethodSignatureIndex <= byte.MaxValue
- ? CilOpCodes.Starg_S
- : CilOpCodes.Starg;
+ if (parameter.MethodSignatureIndex <= byte.MaxValue)
+ code = CilOpCodes.Starg_S;
+ }
+ else if (instruction.OpCode.Code == CilCode.Ldarga)
+ {
+ if (parameter.Index is >= byte.MinValue and <= byte.MaxValue)
+ code = CilOpCodes.Ldarga_S;
}
if (code != instruction.OpCode)
diff --git a/src/AsmResolver.DotNet/Collections/MemberCollection.cs b/src/AsmResolver.DotNet/Collections/MemberCollection.cs
new file mode 100644
index 000000000..1803c3141
--- /dev/null
+++ b/src/AsmResolver.DotNet/Collections/MemberCollection.cs
@@ -0,0 +1,31 @@
+using AsmResolver.Collections;
+
+namespace AsmResolver.DotNet.Collections
+{
+ ///
+ /// Represents an indexed member collection where each member is owned by some object, and prevents the member from
+ /// being added to any other instance of the collection.
+ ///
+ /// The type of the owner object.
+ /// The type of elements to store.
+ public class MemberCollection : OwnedCollection
+ where TOwner : class
+ where TMember : class, IOwnedCollectionElement
+ {
+ internal MemberCollection(TOwner owner)
+ : base(owner)
+ {
+ }
+
+ internal MemberCollection(TOwner owner, int capacity)
+ : base(owner, capacity)
+ {
+ }
+
+ internal void AddNoOwnerCheck(TMember member)
+ {
+ member.Owner = Owner;
+ Items.Add(member);
+ }
+ }
+}
diff --git a/src/AsmResolver.DotNet/Collections/MethodSemanticsCollection.cs b/src/AsmResolver.DotNet/Collections/MethodSemanticsCollection.cs
index 35cfefda3..12f403669 100644
--- a/src/AsmResolver.DotNet/Collections/MethodSemanticsCollection.cs
+++ b/src/AsmResolver.DotNet/Collections/MethodSemanticsCollection.cs
@@ -1,15 +1,13 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
-using AsmResolver.Collections;
namespace AsmResolver.DotNet.Collections
{
///
/// Provides an implementation of a list of method semantics that are associated to a property or event.
///
- public class MethodSemanticsCollection : OwnedCollection< IHasSemantics, MethodSemantics>
+ public class MethodSemanticsCollection : MemberCollection
{
///
/// Creates a new instance of the class.
@@ -36,7 +34,7 @@ internal bool ValidateMembership
set;
} = true;
- private void AssertSemanticsValidity([NotNull] MethodSemantics item)
+ private void AssertSemanticsValidity(MethodSemantics item)
{
if (!ValidateMembership)
return;
diff --git a/src/AsmResolver.DotNet/ModuleDefinition.cs b/src/AsmResolver.DotNet/ModuleDefinition.cs
index e539a0197..2ecd38a2e 100644
--- a/src/AsmResolver.DotNet/ModuleDefinition.cs
+++ b/src/AsmResolver.DotNet/ModuleDefinition.cs
@@ -34,8 +34,6 @@ public class ModuleDefinition :
IHasCustomAttribute,
IOwnedCollectionElement
{
- private static MethodInfo? GetHINSTANCEMethod;
-
private readonly LazyVariable _name;
private readonly LazyVariable _mvid;
private readonly LazyVariable _encId;
@@ -166,14 +164,9 @@ public static ModuleDefinition FromModuleBaseAddress(IntPtr hInstance, PEMapping
/// The module.
public static ModuleDefinition FromModule(Module module, ModuleReaderParameters readerParameters)
{
- // We get the base address using GetHINSTANCE, but this method is unfortunately not shipped with
- // .NET Standard 2.0, so we need to resort to reflection for this.
- GetHINSTANCEMethod ??= typeof(Marshal).GetMethod("GetHINSTANCE", new[] { typeof(Module) });
-
- var handle = (IntPtr) GetHINSTANCEMethod?.Invoke(null, new object[] { module })!;
- if (handle == IntPtr.Zero)
+ if (!ReflectionHacks.TryGetHINSTANCE(module, out var handle))
throw new NotSupportedException("The current platform does not support getting the base address of an instance of System.Reflection.Module.");
- if (handle == (IntPtr) (-1))
+ if (handle == -1)
throw new NotSupportedException("Provided module does not have a module base address.");
// Dynamically loaded modules are in their unmapped form, as opposed to modules loaded normally by the
@@ -302,7 +295,6 @@ public ModuleDefinition(Utf8String? name)
Name = name;
CorLibTypeFactory = CorLibTypeFactory.CreateMscorlib40TypeFactory(this);
- AssemblyReferences.Add((AssemblyReference)CorLibTypeFactory.CorLibScope);
MetadataResolver = new DefaultMetadataResolver(new DotNetFrameworkAssemblyResolver());
TopLevelTypes.Add(new TypeDefinition(null, TypeDefinition.ModuleTypeName, 0));
diff --git a/src/AsmResolver.DotNet/ReferenceImporter.cs b/src/AsmResolver.DotNet/ReferenceImporter.cs
index c9c2b26c7..f2748e2ef 100644
--- a/src/AsmResolver.DotNet/ReferenceImporter.cs
+++ b/src/AsmResolver.DotNet/ReferenceImporter.cs
@@ -311,6 +311,8 @@ public virtual TypeSignature ImportTypeSignature(Type type)
return new GenericParameterSignature(
type.DeclaringMethod != null ? GenericParameterType.Method : GenericParameterType.Type,
type.GenericParameterPosition);
+ if (ReflectionHacks.GetIsFunctionPointer(type))
+ return ImportFunctionPointerType(type);
var corlibType = TargetModule.CorLibTypeFactory.FromName(type.Namespace, type.Name);
if (corlibType != null)
@@ -355,6 +357,41 @@ private TypeSignature ImportGenericType(Type type)
return result;
}
+ private TypeSignature ImportFunctionPointerType(Type type)
+ {
+ var returnType = ImportTypeSignature(ReflectionHacks.GetFunctionPointerReturnType(type));
+ var callConvs = ReflectionHacks.GetFunctionPointerCallingConventions(type);
+ var callConv = CallingConventionAttributes.Default;
+ if (callConvs.Length == 1)
+ {
+ var cc = callConvs[0];
+ callConv = cc.FullName switch
+ {
+ "System.Runtime.CompilerServices.CallConvCdecl" => CallingConventionAttributes.C,
+ "System.Runtime.CompilerServices.CallConvFastcall" => CallingConventionAttributes.FastCall,
+ "System.Runtime.CompilerServices.CallConvStdcall" => CallingConventionAttributes.StdCall,
+ "System.Runtime.CompilerServices.CallConvThiscall" => CallingConventionAttributes.ThisCall,
+ _ => CallingConventionAttributes.Default
+ };
+ if (callConv == CallingConventionAttributes.Default)
+ returnType = returnType.MakeModifierType(ImportType(cc), false);
+ }
+ else
+ {
+ foreach (var cc in callConvs)
+ returnType = returnType.MakeModifierType(ImportType(cc), false);
+ }
+
+ if (callConv == default && ReflectionHacks.GetIsUnmanagedFunctionPointer(type))
+ callConv = CallingConventionAttributes.Unmanaged;
+
+ return new MethodSignature(
+ callConv,
+ returnType,
+ ReflectionHacks.GetFunctionPointerParameterTypes(type).Select(ImportTypeSignature)
+ ).MakeFunctionPointerType();
+ }
+
///
/// Imports a reference to- or an instantiation of a method into the module.
///
diff --git a/src/AsmResolver.DotNet/ReflectionHacks.cs b/src/AsmResolver.DotNet/ReflectionHacks.cs
new file mode 100644
index 000000000..739398c2c
--- /dev/null
+++ b/src/AsmResolver.DotNet/ReflectionHacks.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace AsmResolver.DotNet
+{
+ internal static class ReflectionHacks
+ {
+#if !NET8_0_OR_GREATER
+ private static readonly PropertyInfo? IsFunctionPointerProp = typeof(Type).GetProperty("IsFunctionPointer");
+ private static readonly PropertyInfo? IsUnmanagedFunctionPointerProp = typeof(Type).GetProperty("IsUnmanagedFunctionPointer");
+ private static readonly MethodInfo? GetFunctionPointerReturnTypeMethod = typeof(Type).GetMethod("GetFunctionPointerReturnType", Array.Empty());
+ private static readonly MethodInfo? GetFunctionPointerCallingConventionsMethod = typeof(Type).GetMethod("GetFunctionPointerCallingConventions", Array.Empty());
+ private static readonly MethodInfo? GetFunctionPointerParameterTypesMethod = typeof(Type).GetMethod("GetFunctionPointerParameterTypes", Array.Empty());
+#endif
+#if NETSTANDARD2_0
+ private static readonly MethodInfo? GetHINSTANCEMethod = typeof(Marshal).GetMethod("GetHINSTANCE", new[] { typeof(Module) });
+#endif
+
+ internal static bool GetIsFunctionPointer(Type t)
+ {
+#if NET8_0_OR_GREATER
+ return t.IsFunctionPointer;
+#else
+ return IsFunctionPointerProp != null && (bool)IsFunctionPointerProp.GetValue(t)!;
+#endif
+ }
+
+ internal static bool GetIsUnmanagedFunctionPointer(Type t)
+ {
+#if NET8_0_OR_GREATER
+ return t.IsUnmanagedFunctionPointer;
+#else
+ // can only be called if the type was already verified to be a function pointer
+ // therefore the PropertyInfo is not null
+ return (bool)IsUnmanagedFunctionPointerProp!.GetValue(t)!;
+#endif
+ }
+
+ internal static Type GetFunctionPointerReturnType(Type t)
+ {
+#if NET8_0_OR_GREATER
+ return t.GetFunctionPointerReturnType();
+#else
+ // can only be called if the type was already verified to be a function pointer
+ // therefore the MethodInfo is not null
+ return (Type)GetFunctionPointerReturnTypeMethod!.Invoke(t, null)!;
+#endif
+ }
+
+ internal static Type[] GetFunctionPointerCallingConventions(Type t)
+ {
+#if NET8_0_OR_GREATER
+ return t.GetFunctionPointerCallingConventions();
+#else
+ // can only be called if the type was already verified to be a function pointer
+ // therefore the MethodInfo is not null
+ return (Type[])GetFunctionPointerCallingConventionsMethod!.Invoke(t, null)!;
+#endif
+ }
+
+ internal static Type[] GetFunctionPointerParameterTypes(Type t)
+ {
+#if NET8_0_OR_GREATER
+ return t.GetFunctionPointerParameterTypes();
+#else
+ // can only be called if the type was already verified to be a function pointer
+ // therefore the MethodInfo is not null
+ return (Type[])GetFunctionPointerParameterTypesMethod!.Invoke(t, null)!;
+#endif
+ }
+
+ internal static bool TryGetHINSTANCE(Module m, out nint hinstance)
+ {
+#if !NETSTANDARD2_0
+ hinstance = Marshal.GetHINSTANCE(m);
+ return true;
+#else
+ if (GetHINSTANCEMethod == null)
+ {
+ hinstance = default;
+ return false;
+ }
+ hinstance = (nint)GetHINSTANCEMethod.Invoke(null, new object[] { m });
+ return true;
+#endif
+ }
+ }
+}
diff --git a/src/AsmResolver.DotNet/Serialized/SerializedAssemblyDefinition.cs b/src/AsmResolver.DotNet/Serialized/SerializedAssemblyDefinition.cs
index 3af420240..d6e254453 100644
--- a/src/AsmResolver.DotNet/Serialized/SerializedAssemblyDefinition.cs
+++ b/src/AsmResolver.DotNet/Serialized/SerializedAssemblyDefinition.cs
@@ -2,8 +2,7 @@
using System.Collections.Generic;
using System.Runtime.Versioning;
using AsmResolver.Collections;
-using AsmResolver.PE.DotNet.Metadata.Blob;
-using AsmResolver.PE.DotNet.Metadata.Strings;
+using AsmResolver.DotNet.Collections;
using AsmResolver.PE.DotNet.Metadata.Tables;
using AsmResolver.PE.DotNet.Metadata.Tables.Rows;
using FileAttributes = AsmResolver.PE.DotNet.Metadata.Tables.Rows.FileAttributes;
@@ -58,11 +57,8 @@ public SerializedAssemblyDefinition(
///
protected override IList GetModules()
{
- _manifestModule.Assembly = null;
- var result = new OwnedCollection(this)
- {
- _manifestModule
- };
+ var result = new MemberCollection(this);
+ result.AddNoOwnerCheck(_manifestModule);
var moduleResolver = _context.Parameters.ModuleResolver;
if (moduleResolver is not null)
diff --git a/src/AsmResolver.DotNet/Serialized/SerializedEventDefinition.cs b/src/AsmResolver.DotNet/Serialized/SerializedEventDefinition.cs
index 086de5b61..bcbb9aff5 100644
--- a/src/AsmResolver.DotNet/Serialized/SerializedEventDefinition.cs
+++ b/src/AsmResolver.DotNet/Serialized/SerializedEventDefinition.cs
@@ -69,7 +69,7 @@ protected override IList GetSemantics()
foreach (uint rid in module.GetMethodSemantics(MetadataToken))
{
var semanticsToken = new MetadataToken(TableIndex.MethodSemantics, rid);
- result.Add((MethodSemantics) module.LookupMember(semanticsToken));
+ result.AddNoOwnerCheck((MethodSemantics) module.LookupMember(semanticsToken));
}
result.ValidateMembership = true;
diff --git a/src/AsmResolver.DotNet/Serialized/SerializedGenericParameter.cs b/src/AsmResolver.DotNet/Serialized/SerializedGenericParameter.cs
index 592a6ef1a..db448b1db 100644
--- a/src/AsmResolver.DotNet/Serialized/SerializedGenericParameter.cs
+++ b/src/AsmResolver.DotNet/Serialized/SerializedGenericParameter.cs
@@ -54,12 +54,12 @@ protected override IList GetConstraints()
{
var module = _context.ParentModule;
var rids = module.GetGenericParameterConstraints(MetadataToken);
- var result = new OwnedCollection(this, rids.Count);
+ var result = new MemberCollection(this, rids.Count);
foreach (uint rid in rids)
{
var constraintToken = new MetadataToken(TableIndex.GenericParamConstraint, rid);
- result.Add((GenericParameterConstraint) module.LookupMember(constraintToken));
+ result.AddNoOwnerCheck((GenericParameterConstraint) module.LookupMember(constraintToken));
}
return result;
diff --git a/src/AsmResolver.DotNet/Serialized/SerializedMethodDefinition.cs b/src/AsmResolver.DotNet/Serialized/SerializedMethodDefinition.cs
index 42675f8ab..046b10039 100644
--- a/src/AsmResolver.DotNet/Serialized/SerializedMethodDefinition.cs
+++ b/src/AsmResolver.DotNet/Serialized/SerializedMethodDefinition.cs
@@ -78,12 +78,12 @@ protected override IList GetSecurityDeclarations() =>
protected override IList GetParameterDefinitions()
{
var parameterRange = _context.ParentModule.GetParameterRange(MetadataToken.Rid);
- var result = new OwnedCollection(this, parameterRange.Count);
+ var result = new MemberCollection(this, parameterRange.Count);
foreach (var token in parameterRange)
{
if (_context.ParentModule.TryLookupMember(token, out var member) && member is ParameterDefinition parameter)
- result.Add(parameter);
+ result.AddNoOwnerCheck(parameter);
}
return result;
@@ -106,14 +106,14 @@ protected override IList GetParameterDefinitions()
protected override IList GetGenericParameters()
{
var rids = _context.ParentModule.GetGenericParameters(MetadataToken);
- var result = new OwnedCollection(this, rids.Count);
+ var result = new MemberCollection(this, rids.Count);
foreach (uint rid in rids)
{
if (_context.ParentModule.TryLookupMember(new MetadataToken(TableIndex.GenericParam, rid), out var member)
&& member is GenericParameter genericParameter)
{
- result.Add(genericParameter);
+ result.AddNoOwnerCheck(genericParameter);
}
}
diff --git a/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.Metadata.cs b/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.Metadata.cs
index 243f31ca5..16a1e0133 100644
--- a/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.Metadata.cs
+++ b/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.Metadata.cs
@@ -229,12 +229,12 @@ internal IList GetCustomAttributeCollection(IHasCustomAttribute
{
EnsureCustomAttributesInitialized();
var rids = _customAttributes.GetValues(owner.MetadataToken);
- var result = new OwnedCollection(owner, rids.Count);
+ var result = new MemberCollection(owner, rids.Count);
foreach (uint rid in rids)
{
var attribute = (CustomAttribute) LookupMember(new MetadataToken(TableIndex.CustomAttribute, rid));
- result.Add(attribute);
+ result.AddNoOwnerCheck(attribute);
}
return result;
@@ -274,12 +274,12 @@ internal IList GetSecurityDeclarationCollection(IHasSecurit
{
EnsureSecurityDeclarationsInitialized();
var rids = _securityDeclarations.GetValues(owner.MetadataToken);
- var result = new OwnedCollection(owner, rids.Count);
+ var result = new MemberCollection(owner, rids.Count);
foreach (uint rid in rids)
{
var attribute = (SecurityDeclaration) LookupMember(new MetadataToken(TableIndex.DeclSecurity, rid));
- result.Add(attribute);
+ result.AddNoOwnerCheck(attribute);
}
return result;
diff --git a/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.cs b/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.cs
index 464553d67..c5063f1b4 100644
--- a/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.cs
+++ b/src/AsmResolver.DotNet/Serialized/SerializedModuleDefinition.cs
@@ -1,17 +1,13 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
-using AsmResolver.Collections;
using AsmResolver.DotNet.Collections;
using AsmResolver.DotNet.Signatures.Types;
using AsmResolver.PE;
using AsmResolver.PE.Debug;
using AsmResolver.PE.DotNet;
-using AsmResolver.PE.DotNet.Metadata.Guid;
-using AsmResolver.PE.DotNet.Metadata.Strings;
using AsmResolver.PE.DotNet.Metadata.Tables;
using AsmResolver.PE.DotNet.Metadata.Tables.Rows;
-using AsmResolver.PE.DotNet.Metadata.UserStrings;
using AsmResolver.PE.Win32Resources;
namespace AsmResolver.DotNet.Serialized
@@ -191,7 +187,7 @@ protected override IList GetTopLevelTypes()
var typeDefTable = ReaderContext.TablesStream.GetTable(TableIndex.TypeDef);
int nestedTypeCount = ReaderContext.TablesStream.GetTable(TableIndex.NestedClass).Count;
- var types = new OwnedCollection(this,
+ var types = new MemberCollection(this,
typeDefTable.Count - nestedTypeCount);
for (int i = 0; i < typeDefTable.Count; i++)
@@ -200,7 +196,7 @@ protected override IList GetTopLevelTypes()
if (_typeDefTree.GetKey(rid) == 0)
{
var token = new MetadataToken(TableIndex.TypeDef, rid);
- types.Add(_memberFactory.LookupTypeDefinition(token)!);
+ types.AddNoOwnerCheck(_memberFactory.LookupTypeDefinition(token)!);
}
}
@@ -212,13 +208,13 @@ protected override IList GetAssemblyReferences()
{
var table = ReaderContext.TablesStream.GetTable(TableIndex.AssemblyRef);
- var result = new OwnedCollection(this, table.Count);
+ var result = new MemberCollection(this, table.Count);
// Don't use the member factory here, this method may be called before the member factory is initialized.
for (int i = 0; i < table.Count; i++)
{
var token = new MetadataToken(TableIndex.AssemblyRef, (uint) i + 1);
- result.Add(new SerializedAssemblyReference(ReaderContext, token, table[i]));
+ result.AddNoOwnerCheck(new SerializedAssemblyReference(ReaderContext, token, table[i]));
}
return result;
@@ -229,13 +225,13 @@ protected override IList GetModuleReferences()
{
var table = ReaderContext.TablesStream.GetTable(TableIndex.ModuleRef);
- var result = new OwnedCollection(this, table.Count);
+ var result = new MemberCollection(this, table.Count);
for (int i = 0; i < table.Count; i++)
{
var token = new MetadataToken(TableIndex.ModuleRef, (uint) i + 1);
if (_memberFactory.TryLookupMember(token, out var member) && member is ModuleReference module)
- result.Add(module);
+ result.AddNoOwnerCheck(module);
}
return result;
@@ -246,13 +242,13 @@ protected override IList GetFileReferences()
{
var table = ReaderContext.TablesStream.GetTable(TableIndex.File);
- var result = new OwnedCollection(this, table.Count);
+ var result = new MemberCollection(this, table.Count);
for (int i = 0; i < table.Count; i++)
{
var token = new MetadataToken(TableIndex.File, (uint) i + 1);
if (_memberFactory.TryLookupMember(token, out var member) && member is FileReference file)
- result.Add(file);
+ result.AddNoOwnerCheck(file);
}
return result;
@@ -263,13 +259,13 @@ protected override IList GetResources()
{
var table = ReaderContext.TablesStream.GetTable(TableIndex.ManifestResource);
- var result = new OwnedCollection(this, table.Count);
+ var result = new MemberCollection(this, table.Count);
for (int i = 0; i < table.Count; i++)
{
var token = new MetadataToken(TableIndex.ManifestResource, (uint) i + 1);
if (_memberFactory.TryLookupMember(token, out var member) && member is ManifestResource resource)
- result.Add(resource);
+ result.AddNoOwnerCheck(resource);
}
return result;
@@ -280,13 +276,13 @@ protected override IList GetExportedTypes()
{
var table = ReaderContext.TablesStream.GetTable(TableIndex.ExportedType);
- var result = new OwnedCollection(this, table.Count);
+ var result = new MemberCollection(this, table.Count);
for (int i = 0; i < table.Count; i++)
{
var token = new MetadataToken(TableIndex.ExportedType, (uint) i + 1);
if (_memberFactory.TryLookupMember(token, out var member) && member is ExportedType exportedType)
- result.Add(exportedType);
+ result.AddNoOwnerCheck(exportedType);
}
return result;
diff --git a/src/AsmResolver.DotNet/Serialized/SerializedPropertyDefinition.cs b/src/AsmResolver.DotNet/Serialized/SerializedPropertyDefinition.cs
index 1d235e66a..ac71f8512 100644
--- a/src/AsmResolver.DotNet/Serialized/SerializedPropertyDefinition.cs
+++ b/src/AsmResolver.DotNet/Serialized/SerializedPropertyDefinition.cs
@@ -76,7 +76,7 @@ protected override IList GetSemantics()
foreach (uint rid in rids)
{
var semanticsToken = new MetadataToken(TableIndex.MethodSemantics, rid);
- result.Add((MethodSemantics) module.LookupMember(semanticsToken));
+ result.AddNoOwnerCheck((MethodSemantics) module.LookupMember(semanticsToken));
}
result.ValidateMembership = true;
diff --git a/src/AsmResolver.DotNet/Serialized/SerializedTypeDefinition.cs b/src/AsmResolver.DotNet/Serialized/SerializedTypeDefinition.cs
index ba495ba5c..60f1096f5 100644
--- a/src/AsmResolver.DotNet/Serialized/SerializedTypeDefinition.cs
+++ b/src/AsmResolver.DotNet/Serialized/SerializedTypeDefinition.cs
@@ -1,10 +1,7 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using AsmResolver.Collections;
using AsmResolver.DotNet.Collections;
-using AsmResolver.PE.DotNet.Metadata;
-using AsmResolver.PE.DotNet.Metadata.Strings;
using AsmResolver.PE.DotNet.Metadata.Tables;
using AsmResolver.PE.DotNet.Metadata.Tables.Rows;
@@ -58,12 +55,12 @@ public SerializedTypeDefinition(ModuleReaderContext context, MetadataToken token
protected override IList GetNestedTypes()
{
var rids = _context.ParentModule.GetNestedTypeRids(MetadataToken.Rid);
- var result = new OwnedCollection(this, rids.Count);
+ var result = new MemberCollection(this, rids.Count);
foreach (uint rid in rids)
{
var nestedType = (TypeDefinition) _context.ParentModule.LookupMember(new MetadataToken(TableIndex.TypeDef, rid));
- result.Add(nestedType);
+ result.AddNoOwnerCheck(nestedType);
}
return result;
@@ -97,10 +94,10 @@ protected override IList GetEvents() =>
private IList CreateMemberCollection(MetadataRange range)
where TMember : class, IMetadataMember, IOwnedCollectionElement
{
- var result = new OwnedCollection(this, range.Count);
+ var result = new MemberCollection(this, range.Count);
foreach (var token in range)
- result.Add((TMember) _context.ParentModule.LookupMember(token));
+ result.AddNoOwnerCheck((TMember) _context.ParentModule.LookupMember(token));
return result;
}
@@ -117,14 +114,14 @@ protected override IList GetSecurityDeclarations() =>
protected override IList GetGenericParameters()
{
var rids = _context.ParentModule.GetGenericParameters(MetadataToken);
- var result = new OwnedCollection(this, rids.Count);
+ var result = new MemberCollection(this, rids.Count);
foreach (uint rid in rids)
{
if (_context.ParentModule.TryLookupMember(new MetadataToken(TableIndex.GenericParam, rid), out var member)
&& member is GenericParameter genericParameter)
{
- result.Add(genericParameter);
+ result.AddNoOwnerCheck(genericParameter);
}
}
@@ -135,14 +132,14 @@ protected override IList GetGenericParameters()
protected override IList GetInterfaces()
{
var rids = _context.ParentModule.GetInterfaceImplementationRids(MetadataToken);
- var result = new OwnedCollection(this, rids.Count);
+ var result = new MemberCollection(this, rids.Count);
foreach (uint rid in rids)
{
if (_context.ParentModule.TryLookupMember(new MetadataToken(TableIndex.InterfaceImpl, rid), out var member)
&& member is InterfaceImplementation type)
{
- result.Add(type);
+ result.AddNoOwnerCheck(type);
}
}
diff --git a/src/AsmResolver.DotNet/Signatures/SignatureComparer.TypeSignature.cs b/src/AsmResolver.DotNet/Signatures/SignatureComparer.TypeSignature.cs
index fa11e5a67..edbacbc2b 100644
--- a/src/AsmResolver.DotNet/Signatures/SignatureComparer.TypeSignature.cs
+++ b/src/AsmResolver.DotNet/Signatures/SignatureComparer.TypeSignature.cs
@@ -208,8 +208,8 @@ public int GetHashCode(CustomModifierTypeSignature obj)
unchecked
{
int hashCode = (int) obj.ElementType << ElementTypeOffset;
- hashCode = (hashCode * 397) ^ obj.ModifierType.GetHashCode();
- hashCode = (hashCode * 397) ^ obj.BaseType.GetHashCode();
+ hashCode = (hashCode * 397) ^ GetHashCode(obj.ModifierType);
+ hashCode = (hashCode * 397) ^ GetHashCode(obj.BaseType);
return hashCode;
}
}
@@ -233,7 +233,7 @@ public int GetHashCode(GenericInstanceTypeSignature obj)
unchecked
{
int hashCode = (int) obj.ElementType << ElementTypeOffset;
- hashCode = (hashCode * 397) ^ obj.GenericType.GetHashCode();
+ hashCode = (hashCode * 397) ^ GetHashCode(obj.GenericType);
hashCode = (hashCode * 397) ^ GetHashCode(obj.TypeArguments);
return hashCode;
}
diff --git a/src/AsmResolver.DotNet/Signatures/Types/CorLibTypeFactory.cs b/src/AsmResolver.DotNet/Signatures/Types/CorLibTypeFactory.cs
index 516342867..2d8075a2f 100644
--- a/src/AsmResolver.DotNet/Signatures/Types/CorLibTypeFactory.cs
+++ b/src/AsmResolver.DotNet/Signatures/Types/CorLibTypeFactory.cs
@@ -136,15 +136,14 @@ public IResolutionScope CorLibScope
/// Gets the element type signature for .
///
public CorLibTypeSignature Object => GetOrCreateCorLibTypeSignature(ref _object, ElementType.Object, nameof(Object));
-
+
///
/// Creates a new type factory that references mscorlib 4.0.0.0.
///
/// The factory.
public static CorLibTypeFactory CreateMscorlib40TypeFactory(ModuleDefinition module)
{
- var importer = new ReferenceImporter(module);
- return new CorLibTypeFactory(importer.ImportScope(KnownCorLibs.MsCorLib_v4_0_0_0));
+ return new CorLibTypeFactory(KnownCorLibs.MsCorLib_v4_0_0_0.ImportWith(module.DefaultImporter));
}
///
diff --git a/src/AsmResolver.PE.File/AsmResolver.PE.File.csproj b/src/AsmResolver.PE.File/AsmResolver.PE.File.csproj
index aa5d496e7..fb00775e4 100644
--- a/src/AsmResolver.PE.File/AsmResolver.PE.File.csproj
+++ b/src/AsmResolver.PE.File/AsmResolver.PE.File.csproj
@@ -4,11 +4,8 @@
AsmResolver.PE.File
Raw PE file models for the AsmResolver executable file inspection toolsuite.
exe pe headers sections inspection manipulation assembly disassembly
- true
1701;1702;NU5105
true
- enable
- net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1
true
@@ -25,9 +22,9 @@
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/AsmResolver.PE.Win32Resources/AsmResolver.PE.Win32Resources.csproj b/src/AsmResolver.PE.Win32Resources/AsmResolver.PE.Win32Resources.csproj
index b2fc17031..98bce0723 100644
--- a/src/AsmResolver.PE.Win32Resources/AsmResolver.PE.Win32Resources.csproj
+++ b/src/AsmResolver.PE.Win32Resources/AsmResolver.PE.Win32Resources.csproj
@@ -3,10 +3,7 @@
AsmResolver.PE.Win32Resources
exe pe directories imports exports resources dotnet cil inspection manipulation assembly disassembly
- true
1701;1702;NU5105
- enable
- net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1
true
@@ -18,11 +15,11 @@
bin\Release\AsmResolver.PE.Win32Resources.xml
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/src/AsmResolver.PE/AsmResolver.PE.csproj b/src/AsmResolver.PE/AsmResolver.PE.csproj
index 1ec5862cf..699fbbd7a 100644
--- a/src/AsmResolver.PE/AsmResolver.PE.csproj
+++ b/src/AsmResolver.PE/AsmResolver.PE.csproj
@@ -4,10 +4,7 @@
AsmResolver.PE
PE image models for the AsmResolver executable file inspection toolsuite.
exe pe directories imports exports resources dotnet cil inspection manipulation assembly disassembly
- true
1701;1702;NU5105
- enable
- net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1
true
@@ -24,7 +21,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/AsmResolver.PE/DotNet/Metadata/Metadata.cs b/src/AsmResolver.PE/DotNet/Metadata/Metadata.cs
index 0066a4ce3..659da6912 100644
--- a/src/AsmResolver.PE/DotNet/Metadata/Metadata.cs
+++ b/src/AsmResolver.PE/DotNet/Metadata/Metadata.cs
@@ -188,9 +188,11 @@ protected virtual void WriteStreamHeaders(IBinaryStreamWriter writer, MetadataSt
var header = headers[i];
writer.WriteUInt32(header.Offset);
writer.WriteUInt32(header.Size);
+
+ ulong nameOffset = writer.Offset;
writer.WriteAsciiString(header.Name);
writer.WriteByte(0);
- writer.Align(4);
+ writer.AlignRelative(4, nameOffset);
}
}
diff --git a/src/AsmResolver.PE/DotNet/Metadata/MetadataStreamHeader.cs b/src/AsmResolver.PE/DotNet/Metadata/MetadataStreamHeader.cs
index da69e89cf..8f76eb69a 100644
--- a/src/AsmResolver.PE/DotNet/Metadata/MetadataStreamHeader.cs
+++ b/src/AsmResolver.PE/DotNet/Metadata/MetadataStreamHeader.cs
@@ -60,7 +60,7 @@ public static MetadataStreamHeader FromReader(ref BinaryStreamReader reader)
uint offset = reader.ReadUInt32();
uint size = reader.ReadUInt32();
string name = reader.ReadAsciiString();
- reader.Align(4);
+ reader.AlignRelative(4);
return new MetadataStreamHeader(offset, size, name);
}
diff --git a/src/AsmResolver.Symbols.Pdb/AsmResolver.Symbols.Pdb.csproj b/src/AsmResolver.Symbols.Pdb/AsmResolver.Symbols.Pdb.csproj
index 1b0c09029..61bad1f34 100644
--- a/src/AsmResolver.Symbols.Pdb/AsmResolver.Symbols.Pdb.csproj
+++ b/src/AsmResolver.Symbols.Pdb/AsmResolver.Symbols.Pdb.csproj
@@ -3,9 +3,6 @@
AsmResolver
Windows PDB models for the AsmResolver executable file inspection toolsuite.
- windows pdb symbols
- enable
- net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1
true
true
@@ -26,9 +23,9 @@
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/AsmResolver/AsmResolver.csproj b/src/AsmResolver/AsmResolver.csproj
index d3591d07c..18ba58436 100644
--- a/src/AsmResolver/AsmResolver.csproj
+++ b/src/AsmResolver/AsmResolver.csproj
@@ -4,10 +4,7 @@
AsmResolver
The base library for the AsmResolver executable file inspection toolsuite.
exe pe dotnet cil inspection manipulation assembly disassembly
- true
1701;1702;NU5105
- enable
- net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1
true
@@ -22,9 +19,9 @@
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/AsmResolver/Collections/OwnedCollection.cs b/src/AsmResolver/Collections/OwnedCollection.cs
index 6facee7e8..b5617dc90 100644
--- a/src/AsmResolver/Collections/OwnedCollection.cs
+++ b/src/AsmResolver/Collections/OwnedCollection.cs
@@ -55,7 +55,7 @@ protected void AssertNotNullAndHasNoOwner(TItem? item)
{
if (item is null)
throw new ArgumentNullException(nameof(item));
- if (item.Owner != null && item.Owner != Owner)
+ if (item.Owner is not null)
throw new ArgumentException("Item is already added to another collection.");
}
diff --git a/src/AsmResolver/IO/IBinaryStreamWriter.cs b/src/AsmResolver/IO/IBinaryStreamWriter.cs
index fe772a3f8..c5ac930c1 100644
--- a/src/AsmResolver/IO/IBinaryStreamWriter.cs
+++ b/src/AsmResolver/IO/IBinaryStreamWriter.cs
@@ -201,10 +201,18 @@ public static void WriteAsciiString(this IBinaryStreamWriter writer, string valu
///
/// The writer to align.
/// The boundary to use.
- public static void Align(this IBinaryStreamWriter writer, uint align)
+ public static void Align(this IBinaryStreamWriter writer, uint align) => writer.AlignRelative(align, 0);
+
+ ///
+ /// Aligns the writer to a specified boundary, relative to the provided start offset..
+ ///
+ /// The writer to align.
+ /// The boundary to use.
+ /// The starting offset to consider the alignment boundaries from.
+ public static void AlignRelative(this IBinaryStreamWriter writer, uint align, ulong startOffset)
{
- ulong currentPosition = writer.Offset;
- writer.WriteZeroes((int) (currentPosition.Align(align) - writer.Offset));
+ ulong currentPosition = writer.Offset - startOffset;
+ writer.WriteZeroes((int) (currentPosition.Align(align) - currentPosition));
}
///
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
new file mode 100644
index 000000000..93a6227cc
--- /dev/null
+++ b/src/Directory.Build.props
@@ -0,0 +1,10 @@
+
+
+
+
+ net8.0;net6.0;netcoreapp3.1;netstandard2.0;netstandard2.1
+ true
+ enable
+ $(MSBuildThisFileDirectory)..\artifacts
+
+
diff --git a/test/AsmResolver.Benchmarks/AsmResolver.Benchmarks.csproj b/test/AsmResolver.Benchmarks/AsmResolver.Benchmarks.csproj
index 864745258..0f275278b 100644
--- a/test/AsmResolver.Benchmarks/AsmResolver.Benchmarks.csproj
+++ b/test/AsmResolver.Benchmarks/AsmResolver.Benchmarks.csproj
@@ -2,7 +2,7 @@
Exe
- net6.0
+ net8.0
enable
diff --git a/test/AsmResolver.DotNet.Dynamic.Tests/AsmResolver.DotNet.Dynamic.Tests.csproj b/test/AsmResolver.DotNet.Dynamic.Tests/AsmResolver.DotNet.Dynamic.Tests.csproj
index aa91f3a42..8b3a79e64 100644
--- a/test/AsmResolver.DotNet.Dynamic.Tests/AsmResolver.DotNet.Dynamic.Tests.csproj
+++ b/test/AsmResolver.DotNet.Dynamic.Tests/AsmResolver.DotNet.Dynamic.Tests.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net8.0
disable
false
@@ -9,9 +9,9 @@
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/test/AsmResolver.DotNet.Dynamic.Tests/DynamicMethodDefinitionTest.cs b/test/AsmResolver.DotNet.Dynamic.Tests/DynamicMethodDefinitionTest.cs
index c649f621d..94a8a4174 100644
--- a/test/AsmResolver.DotNet.Dynamic.Tests/DynamicMethodDefinitionTest.cs
+++ b/test/AsmResolver.DotNet.Dynamic.Tests/DynamicMethodDefinitionTest.cs
@@ -54,7 +54,7 @@ public void RtDynamicMethod()
object rtDynamicMethod = generatedDynamicMethod
.GetType()
.GetField("m_dynMethod", (BindingFlags) (-1))?
- .GetValue(generatedDynamicMethod);
+ .GetValue(generatedDynamicMethod) ?? generatedDynamicMethod;
var dynamicMethod = new DynamicMethodDefinition(module, rtDynamicMethod!);
Assert.NotNull(dynamicMethod);
diff --git a/test/AsmResolver.DotNet.Tests/AsmResolver.DotNet.Tests.csproj b/test/AsmResolver.DotNet.Tests/AsmResolver.DotNet.Tests.csproj
index c9a4eb306..bd8c4745e 100644
--- a/test/AsmResolver.DotNet.Tests/AsmResolver.DotNet.Tests.csproj
+++ b/test/AsmResolver.DotNet.Tests/AsmResolver.DotNet.Tests.csproj
@@ -1,20 +1,22 @@
- net6.0
+ net8.0
false
disable
11
+
+ true
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/test/AsmResolver.DotNet.Tests/Code/Cil/CilInstructionCollectionTest.cs b/test/AsmResolver.DotNet.Tests/Code/Cil/CilInstructionCollectionTest.cs
index 78eab1163..c3ad3549b 100644
--- a/test/AsmResolver.DotNet.Tests/Code/Cil/CilInstructionCollectionTest.cs
+++ b/test/AsmResolver.DotNet.Tests/Code/Cil/CilInstructionCollectionTest.cs
@@ -62,7 +62,7 @@ public void OptimizeFirst4ArgumentsToMacros(int index, CilCode expectedMacro)
public void OptimizeHiddenThisToLdarg0()
{
var instructions = CreateDummyMethod(true, 0, 0);
- instructions.Add(CilOpCodes.Ldarg, instructions.Owner.Owner.Parameters.ThisParameter);
+ instructions.Add(CilOpCodes.Ldarg, instructions.Owner.Owner.Parameters.ThisParameter!);
instructions.Add(CilOpCodes.Ret);
instructions.OptimizeMacros();
@@ -183,6 +183,23 @@ public void OptimizeLoadLocalInstructions(int index, CilCode expected)
Assert.Equal(expected, instructions[0].OpCode.Code);
}
+ [Theory]
+ [InlineData(0, CilCode.Ldloca_S)]
+ [InlineData(1, CilCode.Ldloca_S)]
+ [InlineData(255, CilCode.Ldloca_S)]
+ [InlineData(256, CilCode.Ldloca)]
+ public void OptimizeLoadLocalAddressInstructions(int index, CilCode expected)
+ {
+ var instructions = CreateDummyMethod(false, 0, index + 1);
+
+ instructions.Add(CilOpCodes.Ldloca, instructions.Owner.LocalVariables[index]);
+ instructions.Add(CilOpCodes.Ret);
+
+ instructions.OptimizeMacros();
+
+ Assert.Equal(expected, instructions[0].OpCode.Code);
+ }
+
[Theory]
[InlineData(0, CilCode.Stloc_0)]
[InlineData(1, CilCode.Stloc_1)]
@@ -225,6 +242,24 @@ public void OptimizeLoadArgInstructions(int index, CilCode expected)
Assert.Equal(expected, instructions[0].OpCode.Code);
}
+ [Theory]
+ [InlineData(0, CilCode.Ldarga_S)]
+ [InlineData(1, CilCode.Ldarga_S)]
+ [InlineData(255, CilCode.Ldarga_S)]
+ [InlineData(256, CilCode.Ldarga)]
+ public void OptimizeLoadArgAddressInstructions(int index, CilCode expected)
+ {
+ var instructions = CreateDummyMethod(false, index + 1, 0);
+ var method = instructions.Owner.Owner;
+
+ instructions.Add(CilOpCodes.Ldarga, method.Parameters[index]);
+ instructions.Add(CilOpCodes.Ret);
+
+ instructions.OptimizeMacros();
+
+ Assert.Equal(expected, instructions[0].OpCode.Code);
+ }
+
[Theory]
[InlineData(0, CilCode.Starg_S)]
[InlineData(255, CilCode.Starg_S)]
@@ -374,7 +409,7 @@ public void OptimizeShouldUpdateOffsets()
instructions.OptimizeMacros();
int[] offsets = instructions.Select(i => i.Offset).ToArray();
- Assert.NotEqual(offsets, instructions.Select(i => 0));
+ Assert.All(offsets.Skip(1), offset => Assert.NotEqual(0, offset));
instructions.CalculateOffsets();
Assert.Equal(offsets, instructions.Select(i => i.Offset));
}
@@ -393,7 +428,7 @@ public void ExpandShouldUpdateOffsets()
instructions.ExpandMacros();
int[] offsets = instructions.Select(i => i.Offset).ToArray();
- Assert.NotEqual(offsets, instructions.Select(i => 0));
+ Assert.All(offsets.Skip(1), offset => Assert.NotEqual(0, offset));
instructions.CalculateOffsets();
Assert.Equal(offsets, instructions.Select(i => i.Offset));
}
diff --git a/test/AsmResolver.DotNet.Tests/FieldDefinitionTest.cs b/test/AsmResolver.DotNet.Tests/FieldDefinitionTest.cs
index 3e0c4b177..ba53b1598 100644
--- a/test/AsmResolver.DotNet.Tests/FieldDefinitionTest.cs
+++ b/test/AsmResolver.DotNet.Tests/FieldDefinitionTest.cs
@@ -6,6 +6,7 @@
using AsmResolver.DotNet.TestCases.Fields;
using AsmResolver.DotNet.TestCases.Types.Structs;
using AsmResolver.PE.DotNet.Cil;
+using AsmResolver.PE.DotNet.Metadata.Tables.Rows;
using Xunit;
namespace AsmResolver.DotNet.Tests
@@ -198,6 +199,25 @@ public void PersistentFieldOffset(string name, int offset)
Assert.Equal(offset, newField.FieldOffset);
}
+ [Fact]
+ public void AddSameFieldTwiceToTypeShouldThrow()
+ {
+ var module = new ModuleDefinition("SomeModule");
+ var field = new FieldDefinition("SomeField", FieldAttributes.Public, module.CorLibTypeFactory.Int32);
+ var type = new TypeDefinition("SomeNamespace", "SomeType", TypeAttributes.Public);
+ type.Fields.Add(field);
+ Assert.Throws(() => type.Fields.Add(field));
+ }
+ [Fact]
+ public void AddSameFieldToDifferentTypesShouldThrow()
+ {
+ var module = new ModuleDefinition("SomeModule");
+ var field = new FieldDefinition("SomeField", FieldAttributes.Public, module.CorLibTypeFactory.Int32);
+ var type1 = new TypeDefinition("SomeNamespace", "SomeType1", TypeAttributes.Public);
+ var type2 = new TypeDefinition("SomeNamespace", "SomeType2", TypeAttributes.Public);
+ type1.Fields.Add(field);
+ Assert.Throws(() => type2.Fields.Add(field));
+ }
}
}
diff --git a/test/AsmResolver.DotNet.Tests/ModuleDefinitionTest.cs b/test/AsmResolver.DotNet.Tests/ModuleDefinitionTest.cs
index 8d992d293..2f917dfb9 100644
--- a/test/AsmResolver.DotNet.Tests/ModuleDefinitionTest.cs
+++ b/test/AsmResolver.DotNet.Tests/ModuleDefinitionTest.cs
@@ -167,7 +167,7 @@ public void ReadTypesNoNested()
public void ReadTypesNested()
{
var module = ModuleDefinition.FromFile(typeof(TopLevelClass1).Assembly.Location);
- Assert.Equal(new HashSet
+ Assert.Equal(new Utf8String[]
{
"",
nameof(TopLevelClass1),
diff --git a/test/AsmResolver.DotNet.Tests/ReferenceImporterTest.cs b/test/AsmResolver.DotNet.Tests/ReferenceImporterTest.cs
index 4f745efc9..884420334 100644
--- a/test/AsmResolver.DotNet.Tests/ReferenceImporterTest.cs
+++ b/test/AsmResolver.DotNet.Tests/ReferenceImporterTest.cs
@@ -546,5 +546,60 @@ public void ImportGenericMethodInstantiationWithReturnTypeViaReflection()
var signature = Assert.IsAssignableFrom(imported.Signature.ReturnType);
Assert.Equal(2, signature.Index);
}
+
+#if NET8_0_OR_GREATER
+ private static unsafe class DelegatePointerHolder
+ {
+ public static delegate*unmanaged[Cdecl, SuppressGCTransition] Complex = null;
+ public static delegate*unmanaged[Stdcall] StdcallOnly = null;
+ public static delegate*unmanaged[SuppressGCTransition] GcOnly = null;
+ }
+
+ [Fact]
+ public void ImportComplexFunctionPointerFromReflectedFieldType()
+ {
+ var fieldType = typeof(DelegatePointerHolder).GetField("Complex")!.GetModifiedFieldType();
+ var imported = Assert.IsAssignableFrom(_importer.ImportType(fieldType).ToTypeSignature());
+ Assert.Equal(CallingConventionAttributes.Unmanaged, imported.Signature.CallingConvention);
+ var firstModifier = Assert.IsAssignableFrom(imported.Signature.ReturnType);
+ Assert.True(firstModifier.ModifierType is
+ {
+ Namespace.Value: "System.Runtime.CompilerServices",
+ Name.Value: "CallConvCdecl" or "CallConvSuppressGCTransition"
+ });
+ var secondModifier = Assert.IsAssignableFrom(firstModifier.BaseType);
+ Assert.True(secondModifier.ModifierType is
+ {
+ Namespace.Value: "System.Runtime.CompilerServices",
+ Name.Value: "CallConvCdecl" or "CallConvSuppressGCTransition"
+ });
+ }
+
+ [Fact]
+ public void ImportSimpleFunctionPointerFromReflectedFieldType()
+ {
+ var fieldType = typeof(DelegatePointerHolder).GetField("StdcallOnly")!.GetModifiedFieldType();
+ var imported = Assert.IsAssignableFrom(_importer.ImportType(fieldType).ToTypeSignature());
+ Assert.Equal(CallingConventionAttributes.StdCall, imported.Signature.CallingConvention);
+ }
+
+ [Fact]
+ public void ImportModoptOnlyFunctionPointerFromReflectedFieldType()
+ {
+ var fieldType = typeof(DelegatePointerHolder).GetField("GcOnly")!.GetModifiedFieldType();
+ var imported = Assert.IsAssignableFrom(_importer.ImportType(fieldType).ToTypeSignature());
+ Assert.Equal(CallingConventionAttributes.Unmanaged, imported.Signature.CallingConvention);
+ var firstModifier = Assert.IsAssignableFrom(imported.Signature.ReturnType);
+ Assert.Equal("System.Runtime.CompilerServices.CallConvSuppressGCTransition", firstModifier.ModifierType.FullName);
+ }
+
+ [Fact]
+ public void ImportFunctionPointerFromTypeof()
+ {
+ var imported = Assert.IsAssignableFrom(_importer.ImportType(typeof(delegate*)).ToTypeSignature());
+ Assert.Collection(imported.Signature.ParameterTypes, t => Assert.Same(_module.CorLibTypeFactory.Int32, t));
+ Assert.Same(imported.Signature.ReturnType, _module.CorLibTypeFactory.UInt32);
+ }
+#endif
}
}
diff --git a/test/AsmResolver.DotNet.Tests/TypeDefinitionTest.cs b/test/AsmResolver.DotNet.Tests/TypeDefinitionTest.cs
index 4e2ebfa28..fe59cc058 100644
--- a/test/AsmResolver.DotNet.Tests/TypeDefinitionTest.cs
+++ b/test/AsmResolver.DotNet.Tests/TypeDefinitionTest.cs
@@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using AsmResolver.DotNet.Builder;
+using AsmResolver.DotNet.Code.Cil;
using AsmResolver.DotNet.Signatures;
using AsmResolver.DotNet.Signatures.Types;
using AsmResolver.DotNet.TestCases.CustomAttributes;
@@ -13,6 +15,7 @@
using AsmResolver.DotNet.TestCases.Properties;
using AsmResolver.DotNet.TestCases.Types;
using AsmResolver.DotNet.TestCases.Types.Structs;
+using AsmResolver.PE.DotNet.Cil;
using AsmResolver.PE.DotNet.Metadata.Tables;
using AsmResolver.PE.DotNet.Metadata.Tables.Rows;
using Xunit;
@@ -135,42 +138,42 @@ public void ReadNestedTypes()
var module = ModuleDefinition.FromFile(typeof(TopLevelClass1).Assembly.Location);
var class1 = module.TopLevelTypes.First(t => t.Name == nameof(TopLevelClass1));
- Assert.Equal(new HashSet
+ Assert.Equal(new Utf8String[]
{
nameof(TopLevelClass1.Nested1),
nameof(TopLevelClass1.Nested2)
}, class1.NestedTypes.Select(t => t.Name));
var nested1 = class1.NestedTypes.First(t => t.Name == nameof(TopLevelClass1.Nested1));
- Assert.Equal(new HashSet
+ Assert.Equal(new Utf8String[]
{
nameof(TopLevelClass1.Nested1.Nested1Nested1),
nameof(TopLevelClass1.Nested1.Nested1Nested2)
}, nested1.NestedTypes.Select(t => t.Name));
var nested2 = class1.NestedTypes.First(t => t.Name == nameof(TopLevelClass1.Nested2));
- Assert.Equal(new HashSet
+ Assert.Equal(new Utf8String[]
{
nameof(TopLevelClass1.Nested2.Nested2Nested1),
nameof(TopLevelClass1.Nested2.Nested2Nested2)
}, nested2.NestedTypes.Select(t => t.Name));
var class2 = module.TopLevelTypes.First(t => t.Name == nameof(TopLevelClass2));
- Assert.Equal(new HashSet
+ Assert.Equal(new Utf8String[]
{
nameof(TopLevelClass2.Nested3),
nameof(TopLevelClass2.Nested4)
}, class2.NestedTypes.Select(t => t.Name));
var nested3 = class2.NestedTypes.First(t => t.Name == nameof(TopLevelClass2.Nested3));
- Assert.Equal(new HashSet
+ Assert.Equal(new Utf8String[]
{
nameof(TopLevelClass2.Nested3.Nested3Nested1),
nameof(TopLevelClass2.Nested3.Nested3Nested2)
}, nested3.NestedTypes.Select(t => t.Name));
var nested4 = class2.NestedTypes.First(t => t.Name == nameof(TopLevelClass2.Nested4));
- Assert.Equal(new HashSet
+ Assert.Equal(new Utf8String[]
{
nameof(TopLevelClass2.Nested4.Nested4Nested1),
nameof(TopLevelClass2.Nested4.Nested4Nested2)
@@ -198,8 +201,10 @@ public void ReadNestedFullName()
public void ReadNestedNestedFullName()
{
var module = ModuleDefinition.FromFile(typeof(TopLevelClass1).Assembly.Location);
- var type = (TypeDefinition) module.LookupMember(typeof(TopLevelClass1.Nested1.Nested1Nested2).MetadataToken);
- Assert.Equal("AsmResolver.DotNet.TestCases.NestedClasses.TopLevelClass1+Nested1+Nested1Nested2", type.FullName);
+ var type = (TypeDefinition) module.LookupMember(typeof(TopLevelClass1.Nested1.Nested1Nested2)
+ .MetadataToken);
+ Assert.Equal("AsmResolver.DotNet.TestCases.NestedClasses.TopLevelClass1+Nested1+Nested1Nested2",
+ type.FullName);
}
[Fact]
@@ -723,5 +728,55 @@ public void GetNonExistingConstructorShouldReturnNull()
Assert.Null(type.GetConstructor(factory.String));
Assert.Null(type.GetConstructor(factory.String, factory.String));
}
+
+ [Fact]
+ public void AddTypeToModuleShouldSetOwner()
+ {
+ var module = new ModuleDefinition("Dummy");
+ var type = new TypeDefinition("SomeNamespace", "SomeType", TypeAttributes.Public);
+ module.TopLevelTypes.Add(type);
+ Assert.Same(module, type.Module);
+ }
+
+ [Fact]
+ public void AddNestedTypeToModuleShouldSetOwner()
+ {
+ var module = new ModuleDefinition("Dummy");
+ var type1 = new TypeDefinition("SomeNamespace", "SomeType", TypeAttributes.Public);
+ var type2 = new TypeDefinition(null, "NestedType", TypeAttributes.NestedPublic);
+ module.TopLevelTypes.Add(type1);
+ type1.NestedTypes.Add(type2);
+ Assert.Same(type1, type2.DeclaringType);
+ Assert.Same(module, type2.Module);
+ }
+
+ [Fact]
+ public void AddSameTypeTwiceToModuleShouldThrow()
+ {
+ var module = new ModuleDefinition("Dummy");
+ var type = new TypeDefinition("SomeNamespace", "SomeType", TypeAttributes.Public);
+ module.TopLevelTypes.Add(type);
+ Assert.Throws(() => module.TopLevelTypes.Add(type));
+ }
+
+ [Fact]
+ public void AddSameTypeTwiceToNestedTypeShouldThrow()
+ {
+ var type = new TypeDefinition("SomeNamespace", "SomeType", TypeAttributes.Public);
+ var nestedType = new TypeDefinition(null, "SomeType", TypeAttributes.NestedPublic);
+ type.NestedTypes.Add(nestedType);
+ Assert.Throws(() => type.NestedTypes.Add(nestedType));
+ }
+
+ [Fact]
+ public void AddSameNestedTypeToDifferentTypesShouldThrow()
+ {
+ var type1 = new TypeDefinition("SomeNamespace", "SomeType1", TypeAttributes.Public);
+ var type2 = new TypeDefinition("SomeNamespace", "SomeType2", TypeAttributes.Public);
+ var nestedType = new TypeDefinition(null, "SomeType", TypeAttributes.NestedPublic);
+ type1.NestedTypes.Add(nestedType);
+ Assert.Throws(() => type2.NestedTypes.Add(nestedType));
+ }
+
}
}
diff --git a/test/AsmResolver.PE.File.Tests/AsmResolver.PE.File.Tests.csproj b/test/AsmResolver.PE.File.Tests/AsmResolver.PE.File.Tests.csproj
index 99e8aa174..057949751 100644
--- a/test/AsmResolver.PE.File.Tests/AsmResolver.PE.File.Tests.csproj
+++ b/test/AsmResolver.PE.File.Tests/AsmResolver.PE.File.Tests.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net8.0
false
@@ -10,9 +10,9 @@
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/test/AsmResolver.PE.Tests/AsmResolver.PE.Tests.csproj b/test/AsmResolver.PE.Tests/AsmResolver.PE.Tests.csproj
index 01de3b1e4..452bac3e3 100644
--- a/test/AsmResolver.PE.Tests/AsmResolver.PE.Tests.csproj
+++ b/test/AsmResolver.PE.Tests/AsmResolver.PE.Tests.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net8.0
false
true
enable
@@ -17,9 +17,9 @@
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/test/AsmResolver.PE.Tests/DotNet/Cil/CilInstructionTest.cs b/test/AsmResolver.PE.Tests/DotNet/Cil/CilInstructionTest.cs
index 68573748b..80bd69776 100644
--- a/test/AsmResolver.PE.Tests/DotNet/Cil/CilInstructionTest.cs
+++ b/test/AsmResolver.PE.Tests/DotNet/Cil/CilInstructionTest.cs
@@ -18,7 +18,7 @@ public class CilInstructionTest
[InlineData(CilCode.Ldc_I4_7, null, 7)]
[InlineData(CilCode.Ldc_I4_8, null, 8)]
[InlineData(CilCode.Ldc_I4_S, (sbyte) -10, -10)]
- public void GetLdcI4ConstantTest(CilCode code, object operand, int expectedValue)
+ public void GetLdcI4ConstantTest(CilCode code, object? operand, int expectedValue)
{
var instruction = new CilInstruction(code.ToOpCode(), operand);
Assert.Equal(expectedValue, instruction.GetLdcI4Constant());
diff --git a/test/AsmResolver.PE.Tests/DotNet/Metadata/MetadataTest.cs b/test/AsmResolver.PE.Tests/DotNet/Metadata/MetadataTest.cs
index dc4a0740d..0203c7e3d 100644
--- a/test/AsmResolver.PE.Tests/DotNet/Metadata/MetadataTest.cs
+++ b/test/AsmResolver.PE.Tests/DotNet/Metadata/MetadataTest.cs
@@ -34,7 +34,17 @@ public void CorrectStreamHeaders()
var peImage = PEImage.FromBytes(Properties.Resources.HelloWorld);
var metadata = peImage.DotNetDirectory!.Metadata!;
- var expectedNames = new[] {"#~", "#Strings", "#US", "#GUID", "#Blob"};
+ string[] expectedNames = new[] {"#~", "#Strings", "#US", "#GUID", "#Blob"};
+ Assert.Equal(expectedNames, metadata.Streams.Select(s => s.Name));
+ }
+
+ [Fact]
+ public void CorrectStreamHeadersUnalignedMetadataDirectory()
+ {
+ var peImage = PEImage.FromBytes(Properties.Resources.HelloWorld_UnalignedMetadata);
+ var metadata = peImage.DotNetDirectory!.Metadata!;
+
+ string[] expectedNames = new[] {"#~", "#Strings", "#US", "#GUID", "#Blob"};
Assert.Equal(expectedNames, metadata.Streams.Select(s => s.Name));
}
@@ -188,6 +198,5 @@ public void SelectFirstUserStringsStreamInEnCMetadata()
{
AssertCorrectStreamIsSelected(Properties.Resources.HelloWorld_DoubleUserStringsStream_EnC, true);
}
-
}
}
diff --git a/test/AsmResolver.PE.Tests/Properties/Resources.Designer.cs b/test/AsmResolver.PE.Tests/Properties/Resources.Designer.cs
index b006b2bea..a01ff3be2 100644
--- a/test/AsmResolver.PE.Tests/Properties/Resources.Designer.cs
+++ b/test/AsmResolver.PE.Tests/Properties/Resources.Designer.cs
@@ -171,6 +171,13 @@ public static byte[] HelloWorld_ReadyToRun {
}
}
+ public static byte[] HelloWorld_UnalignedMetadata {
+ get {
+ object obj = ResourceManager.GetObject("HelloWorld_UnalignedMetadata", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+
public static byte[] HelloWorldPortablePdb {
get {
object obj = ResourceManager.GetObject("HelloWorldPortablePdb", resourceCulture);
diff --git a/test/AsmResolver.PE.Tests/Properties/Resources.resx b/test/AsmResolver.PE.Tests/Properties/Resources.resx
index 00511e896..e588237b0 100644
--- a/test/AsmResolver.PE.Tests/Properties/Resources.resx
+++ b/test/AsmResolver.PE.Tests/Properties/Resources.resx
@@ -72,6 +72,9 @@
..\Resources\HelloWorld.ReadyToRun.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ ..\Resources\HelloWorld.UnalignedMetadata.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
..\Resources\HelloWorld.pdb;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
diff --git a/test/AsmResolver.PE.Tests/Resources/HelloWorld.UnalignedMetadata.exe b/test/AsmResolver.PE.Tests/Resources/HelloWorld.UnalignedMetadata.exe
new file mode 100644
index 000000000..85a079542
Binary files /dev/null and b/test/AsmResolver.PE.Tests/Resources/HelloWorld.UnalignedMetadata.exe differ
diff --git a/test/AsmResolver.PE.Win32Resources.Tests/AsmResolver.PE.Win32Resources.Tests.csproj b/test/AsmResolver.PE.Win32Resources.Tests/AsmResolver.PE.Win32Resources.Tests.csproj
index 1c80a65b2..9cd8c9b8c 100644
--- a/test/AsmResolver.PE.Win32Resources.Tests/AsmResolver.PE.Win32Resources.Tests.csproj
+++ b/test/AsmResolver.PE.Win32Resources.Tests/AsmResolver.PE.Win32Resources.Tests.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net8.0
false
AsmResolver.PE.Win32Resources.Tests
warnings
@@ -9,9 +9,9 @@
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/test/AsmResolver.Symbols.Pdb.Tests/AsmResolver.Symbols.Pdb.Tests.csproj b/test/AsmResolver.Symbols.Pdb.Tests/AsmResolver.Symbols.Pdb.Tests.csproj
index 364078a8a..ed3cc2a91 100644
--- a/test/AsmResolver.Symbols.Pdb.Tests/AsmResolver.Symbols.Pdb.Tests.csproj
+++ b/test/AsmResolver.Symbols.Pdb.Tests/AsmResolver.Symbols.Pdb.Tests.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net8.0
enable
false
@@ -9,13 +9,9 @@
-
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/test/AsmResolver.Tests/AsmResolver.Tests.csproj b/test/AsmResolver.Tests/AsmResolver.Tests.csproj
index 5a5259bc5..2af29423d 100644
--- a/test/AsmResolver.Tests/AsmResolver.Tests.csproj
+++ b/test/AsmResolver.Tests/AsmResolver.Tests.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net8.0
false
true
enable
@@ -9,9 +9,9 @@
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/test/Directory.Build.props b/test/Directory.Build.props
new file mode 100644
index 000000000..171c6ac9d
--- /dev/null
+++ b/test/Directory.Build.props
@@ -0,0 +1,9 @@
+
+
+
+
+ $(MSBuildThisFileDirectory)..\artifacts\test
+ false
+
+
+
diff --git a/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.Resources/AsmResolver.DotNet.TestCases.Resources.csproj b/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.Resources/AsmResolver.DotNet.TestCases.Resources.csproj
index b4ceea1e3..7a448bff4 100644
--- a/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.Resources/AsmResolver.DotNet.TestCases.Resources.csproj
+++ b/test/TestBinaries/DotNet/AsmResolver.DotNet.TestCases.Resources/AsmResolver.DotNet.TestCases.Resources.csproj
@@ -24,7 +24,7 @@
-
+
diff --git a/test/TestBinaries/DotNet/HelloWorld/HelloWorld.csproj b/test/TestBinaries/DotNet/HelloWorld/HelloWorld.csproj
index b2a147cef..90588ca1e 100644
--- a/test/TestBinaries/DotNet/HelloWorld/HelloWorld.csproj
+++ b/test/TestBinaries/DotNet/HelloWorld/HelloWorld.csproj
@@ -2,7 +2,7 @@
Exe
- net47;netcoreapp3.1;net6.0
+ net47;netcoreapp3.1;net6.0;net8.0
Resources\Icon.ico
true
diff --git a/tools/AsmResolver.PE.Exports.OrdinalMapper/AsmResolver.PE.Exports.OrdinalMapper.csproj b/tools/AsmResolver.PE.Exports.OrdinalMapper/AsmResolver.PE.Exports.OrdinalMapper.csproj
index 399605bab..fb4aa7b71 100644
--- a/tools/AsmResolver.PE.Exports.OrdinalMapper/AsmResolver.PE.Exports.OrdinalMapper.csproj
+++ b/tools/AsmResolver.PE.Exports.OrdinalMapper/AsmResolver.PE.Exports.OrdinalMapper.csproj
@@ -4,6 +4,7 @@
Exe
net472
enable
+ false