[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 System.Collections.Generic;
|
||||||
using Mono.Cecil;
|
using Mono.Cecil;
|
||||||
using Mono.Cecil.Cil;
|
using Mono.Cecil.Cil;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Microsoft.MaciOS.Nnyeah {
|
namespace Microsoft.MaciOS.Nnyeah {
|
||||||
public class MethodTransformations {
|
public class MethodTransformations {
|
||||||
|
@ -446,6 +447,20 @@ namespace Microsoft.MaciOS.Nnyeah {
|
||||||
|
|
||||||
allTransforms.Add (NewFuncXform ("System.TypeCode System.nfloat::GetTypeCode()", moduleToEdit, nfloatTypeRef, typeCodeRef, "GetTypeCode"));
|
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> ();
|
transformTable = new Dictionary<string, Transformation> ();
|
||||||
|
|
||||||
foreach (var xform in allTransforms) {
|
foreach (var xform in allTransforms) {
|
||||||
|
@ -454,6 +469,24 @@ namespace Microsoft.MaciOS.Nnyeah {
|
||||||
return transformTable;
|
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,
|
static Transformation NewOneParamCtorXform (string oldSignature, ModuleDefinition moduleToEdit, TypeReference owningType,
|
||||||
TypeReference parameterType)
|
TypeReference parameterType)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Mono.Cecil.Cil;
|
using Mono.Cecil.Cil;
|
||||||
|
using Mono.Cecil.Rocks;
|
||||||
|
|
||||||
namespace Microsoft.MaciOS.Nnyeah {
|
namespace Microsoft.MaciOS.Nnyeah {
|
||||||
public class Transformation {
|
public class Transformation {
|
||||||
|
@ -39,33 +40,64 @@ namespace Microsoft.MaciOS.Nnyeah {
|
||||||
|
|
||||||
public bool TryPerformTransform (Instruction old, MethodBody body)
|
public bool TryPerformTransform (Instruction old, MethodBody body)
|
||||||
{
|
{
|
||||||
|
var instructionsCopy = CopyInstructions ();
|
||||||
var il = body.GetILProcessor ();
|
var il = body.GetILProcessor ();
|
||||||
|
body.SimplifyMacros ();
|
||||||
switch (Action) {
|
switch (Action) {
|
||||||
case TransformationAction.Remove:
|
case TransformationAction.Remove:
|
||||||
|
var @new = Instruction.Create (OpCodes.Nop);
|
||||||
|
il.InsertAfter (old, @new);
|
||||||
|
PatchReferences (body, old, @new);
|
||||||
il.Remove (old);
|
il.Remove (old);
|
||||||
break;
|
break;
|
||||||
case TransformationAction.Insert:
|
case TransformationAction.Insert:
|
||||||
foreach (var instr in Instructions) {
|
foreach (var instr in instructionsCopy) {
|
||||||
il.InsertBefore (old, AddVariableIfNeeded (body, instr));
|
il.InsertBefore (old, AddVariableIfNeeded (body, instr));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TransformationAction.Append:
|
case TransformationAction.Append:
|
||||||
foreach (var instr in Enumerable.Reverse (Instructions)) {
|
foreach (var instr in Enumerable.Reverse (instructionsCopy)) {
|
||||||
il.InsertAfter (old, AddVariableIfNeeded (body, instr));
|
il.InsertAfter (old, AddVariableIfNeeded (body, instr));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TransformationAction.Replace:
|
case TransformationAction.Replace:
|
||||||
foreach (var instr in Instructions) {
|
foreach (var instr in Enumerable.Reverse (instructionsCopy)) {
|
||||||
il.InsertBefore (old, AddVariableIfNeeded (body, instr));
|
il.InsertAfter (old, AddVariableIfNeeded (body, instr));
|
||||||
}
|
}
|
||||||
|
var newInstr = instructionsCopy [0];
|
||||||
|
PatchReferences (body, old, @newInstr);
|
||||||
il.Remove (old);
|
il.Remove (old);
|
||||||
break;
|
break;
|
||||||
case TransformationAction.Warn:
|
case TransformationAction.Warn:
|
||||||
|
body.OptimizeMacros ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
body.OptimizeMacros ();
|
||||||
return true;
|
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)
|
static Instruction AddVariableIfNeeded (MethodBody body, Instruction instr)
|
||||||
{
|
{
|
||||||
if (instr.Operand is VariableDefinition variable && !body.Variables.Contains (variable))
|
if (instr.Operand is VariableDefinition variable && !body.Variables.Contains (variable))
|
||||||
|
|
Загрузка…
Ссылка в новой задаче