[nnyeah] Fix for branch targets and AVMediaTypes (#15561)
* Fix for branch targets and AVMediaTypes
This commit is contained in:
Родитель
c957b0402a
Коммит
0b872a1683
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
|
||||
namespace Microsoft.MaciOS.Nnyeah {
|
||||
public static class InstructionExtensions {
|
||||
// The ctor for Instruction is internal and there is no clone/copy method,
|
||||
// therefore we have to drill through the types.
|
||||
public static Instruction Copy (this Instruction i)
|
||||
{
|
||||
if (i.Operand is null)
|
||||
return Instruction.Create (i.OpCode);
|
||||
switch (i.Operand) {
|
||||
case TypeReference tr:
|
||||
return Instruction.Create (i.OpCode, tr);
|
||||
case CallSite cs:
|
||||
return Instruction.Create (i.OpCode, cs);
|
||||
case MethodReference mr:
|
||||
return Instruction.Create (i.OpCode, mr);
|
||||
case FieldReference fr:
|
||||
return Instruction.Create (i.OpCode, fr);
|
||||
case string str:
|
||||
return Instruction.Create (i.OpCode, str);
|
||||
case sbyte sb:
|
||||
return Instruction.Create (i.OpCode, sb);
|
||||
case byte b:
|
||||
return Instruction.Create (i.OpCode, b);
|
||||
case int it:
|
||||
return Instruction.Create (i.OpCode, it);
|
||||
case long lg:
|
||||
return Instruction.Create (i.OpCode, lg);
|
||||
case float ft:
|
||||
return Instruction.Create (i.OpCode, ft);
|
||||
case double db:
|
||||
return Instruction.Create (i.OpCode, db);
|
||||
case Instruction instr:
|
||||
return Instruction.Create (i.OpCode, instr);
|
||||
case Instruction [] instrArr:
|
||||
return Instruction.Create (i.OpCode, instrArr);
|
||||
case VariableDefinition vd:
|
||||
return Instruction.Create (i.OpCode, vd);
|
||||
case ParameterDefinition pd:
|
||||
return Instruction.Create (i.OpCode, pd);
|
||||
default: // can't happen (in theory)
|
||||
throw new InvalidOperationException ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.MaciOS.Nnyeah {
|
||||
public class MethodTransformations {
|
||||
|
@ -446,6 +447,20 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
|
||||
allTransforms.Add (NewFuncXform ("System.TypeCode System.nfloat::GetTypeCode()", moduleToEdit, nfloatTypeRef, typeCodeRef, "GetTypeCode"));
|
||||
|
||||
var getConstantRef = GetGetConstantRef (modules.MicrosoftModule, moduleToEdit);
|
||||
|
||||
allTransforms.Add (AVMediaTypeTransform (getConstantRef, "Foundation.NSString AVFoundation.AVMediaType::get_Video()", 0));
|
||||
allTransforms.Add (AVMediaTypeTransform (getConstantRef, "Foundation.NSString AVFoundation.AVMediaType::get_Audio()", 1));
|
||||
allTransforms.Add (AVMediaTypeTransform (getConstantRef, "Foundation.NSString AVFoundation.AVMediaType::get_Text()", 2));
|
||||
allTransforms.Add (AVMediaTypeTransform (getConstantRef, "Foundation.NSString AVFoundation.AVMediaType::get_ClosedCaption()", 3));
|
||||
allTransforms.Add (AVMediaTypeTransform (getConstantRef, "Foundation.NSString AVFoundation.AVMediaType::get_Subtitle()", 4));
|
||||
allTransforms.Add (AVMediaTypeTransform (getConstantRef, "Foundation.NSString AVFoundation.AVMediaType::get_Timecode()", 5));
|
||||
allTransforms.Add (AVMediaTypeTransform (getConstantRef, "Foundation.NSString AVFoundation.AVMediaType::get_TimedMetadata()", 6));
|
||||
allTransforms.Add (AVMediaTypeTransform (getConstantRef, "Foundation.NSString AVFoundation.AVMediaType::get_Muxed()", 7));
|
||||
allTransforms.Add (AVMediaTypeTransform (getConstantRef, "Foundation.NSString AVFoundation.AVMediaType::get_MetadataObject()", 8));
|
||||
allTransforms.Add (AVMediaTypeTransform (getConstantRef, "Foundation.NSString AVFoundation.AVMediaType::get_Metadata()", 9));
|
||||
allTransforms.Add (AVMediaTypeTransform (getConstantRef, "Foundation.NSString AVFoundation.AVMediaType::get_DepthData()", 10));
|
||||
|
||||
transformTable = new Dictionary<string, Transformation> ();
|
||||
|
||||
foreach (var xform in allTransforms) {
|
||||
|
@ -454,6 +469,24 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
return transformTable;
|
||||
}
|
||||
|
||||
static Transformation AVMediaTypeTransform (MethodReference getConstantRef, string oldSignature, int constant)
|
||||
{
|
||||
return new Transformation (oldSignature,
|
||||
TransformationAction.Replace,
|
||||
new List<Instruction> () {
|
||||
Instruction.Create (OpCodes.Ldc_I4, constant),
|
||||
Instruction.Create (OpCodes.Call, getConstantRef),
|
||||
});
|
||||
}
|
||||
|
||||
static MethodReference GetGetConstantRef (ModuleDefinition msModule, ModuleDefinition moduleToEdit)
|
||||
{
|
||||
var mediaTypesExtensionsDef = msModule.GetType ("AVFoundation.AVMediaTypesExtensions");
|
||||
var avMediaTypesExtensionsRef = moduleToEdit.ImportReference (mediaTypesExtensionsDef);
|
||||
var getConstantDef = mediaTypesExtensionsDef.Methods.FirstOrDefault (m => m.Name == "GetConstant");
|
||||
return moduleToEdit.ImportReference (getConstantDef);
|
||||
}
|
||||
|
||||
static Transformation NewOneParamCtorXform (string oldSignature, ModuleDefinition moduleToEdit, TypeReference owningType,
|
||||
TypeReference parameterType)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mono.Cecil.Cil;
|
||||
using Mono.Cecil.Rocks;
|
||||
|
||||
namespace Microsoft.MaciOS.Nnyeah {
|
||||
public class Transformation {
|
||||
|
@ -39,33 +40,64 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
|
||||
public bool TryPerformTransform (Instruction old, MethodBody body)
|
||||
{
|
||||
var instructionsCopy = CopyInstructions ();
|
||||
var il = body.GetILProcessor ();
|
||||
body.SimplifyMacros ();
|
||||
switch (Action) {
|
||||
case TransformationAction.Remove:
|
||||
var @new = Instruction.Create (OpCodes.Nop);
|
||||
il.InsertAfter (old, @new);
|
||||
PatchReferences (body, old, @new);
|
||||
il.Remove (old);
|
||||
break;
|
||||
case TransformationAction.Insert:
|
||||
foreach (var instr in Instructions) {
|
||||
foreach (var instr in instructionsCopy) {
|
||||
il.InsertBefore (old, AddVariableIfNeeded (body, instr));
|
||||
}
|
||||
break;
|
||||
case TransformationAction.Append:
|
||||
foreach (var instr in Enumerable.Reverse (Instructions)) {
|
||||
foreach (var instr in Enumerable.Reverse (instructionsCopy)) {
|
||||
il.InsertAfter (old, AddVariableIfNeeded (body, instr));
|
||||
}
|
||||
break;
|
||||
case TransformationAction.Replace:
|
||||
foreach (var instr in Instructions) {
|
||||
il.InsertBefore (old, AddVariableIfNeeded (body, instr));
|
||||
foreach (var instr in Enumerable.Reverse (instructionsCopy)) {
|
||||
il.InsertAfter (old, AddVariableIfNeeded (body, instr));
|
||||
}
|
||||
var newInstr = instructionsCopy [0];
|
||||
PatchReferences (body, old, @newInstr);
|
||||
il.Remove (old);
|
||||
break;
|
||||
case TransformationAction.Warn:
|
||||
body.OptimizeMacros ();
|
||||
return false;
|
||||
}
|
||||
body.OptimizeMacros ();
|
||||
return true;
|
||||
}
|
||||
|
||||
List<Instruction> CopyInstructions ()
|
||||
{
|
||||
var instrs = new List<Instruction> (Instructions.Count);
|
||||
instrs.AddRange (Instructions.Select (i => i. Copy()));
|
||||
return instrs;
|
||||
}
|
||||
|
||||
static void PatchReferences (MethodBody body, Instruction old, Instruction @new)
|
||||
{
|
||||
foreach (var instruction in body.Instructions) {
|
||||
if (instruction.Operand is Instruction target && target == old) {
|
||||
instruction.Operand = @new;
|
||||
} else if (instruction.Operand is Instruction [] targets) {
|
||||
for (int i = 0; i < targets.Length; i++) {
|
||||
if (targets [i] == old) {
|
||||
targets [i] = @new;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Instruction AddVariableIfNeeded (MethodBody body, Instruction instr)
|
||||
{
|
||||
if (instr.Operand is VariableDefinition variable && !body.Variables.Contains (variable))
|
||||
|
|
Загрузка…
Ссылка в новой задаче