Hi all,
Im using mono-cecil to modify a .xap Silverlight5 application. But
when inserting new instructions after saving and reloading the a
operand for a brtrue.s is 'lost'.. It seams to be a very specific
scenario in which the problem occurs..
If i modify any line of the original code and then try to modify using
Cecil, the problem does not happen.
If i dont import a function the problem does not happen..
The code should insert a WriteLine before exiting the method with a
RET instruction. (I also need to modify the existing instructions to
point not to the RET but to my writeline.. but to simplify the issue
this not done in the code below)
So now im kinda lost in why this happens, am i missing something or is
it something else?
Below both the class to be modified, and the code that modifies it.
Thanks for everyone who can tell what might be wrong in my code.
With kind regards,
PiBa
>> the code modifying the original dll which is in a DotNet4 C# project:
public static void ComputeOffsets(MethodBody body)
{
var offset = 0;
foreach (var instruction in body.Instructions)
{
instruction.Offset = offset;
offset += instruction.GetSize();
}
}
public static MethodDefinition findMethodDefinition(String
sysLibFolder, String typeFullName, String MethodName, String[]
parameters)
{
// retrieve system library that contains the debug object
AssemblyDefinition systemLib =
AssemblyDefinition.ReadAssembly(sysLibFolder);
bool typeFound;
foreach (TypeDefinition type in systemLib.Modules[0].Types)
{
if (type.FullName == typeFullName)
{
typeFound = true;
foreach (MethodDefinition meth in type.Methods)
{
if ((meth.Name == MethodName) && (meth.Parameters.Count ==
parameters.Length))
{
bool OK = true;
for (int i = 0; i < parameters.Length; i++)
{
if (meth.Parameters[i].ParameterType.ToString() !=
parameters[i])
{
OK = false;
break;
}
}
if (OK)
{
return meth;
}
}
}
}
}
return null;
}
private void button5_Click(object sender, EventArgs e)
{
string sysLibFolder = @"C:\Program Files (x86)\Microsoft
Silverlight\5.0.61118.0\system.dll";
MethodDefinition writeLineMethod =
findMethodDefinition(sysLibFolder, "System.Diagnostics.Debug",
"WriteLine", new String[] { "System.String" });
String testFile = @"C:\SilverlightApplicationTestApp\Bin\Release
\SilverlightApplicationTestApp.dll";
AssemblyDefinition injectLibrary =
AssemblyDefinition.ReadAssembly(testFile);
ShowTree(injectLibrary);
foreach (TypeDefinition type in injectLibrary.MainModule.Types)
{
foreach (MethodDefinition meth in type.Methods)
{
if (meth.Name == "OnUpdateSourceOnChangeChanged")
{
ILProcessor worker = meth.Body.GetILProcessor();
MethodReference writeLineMR =
injectLibrary.MainModule.Import(writeLineMethod);
//insert instruction before RET
Instruction inst = meth.Body.Instructions[0];
while (inst != null)
{
if (inst.OpCode == OpCodes.Ret)
{
Instruction retins = inst;
Instruction startInst = worker.Create(OpCodes.Ldstr,
type.Name);
worker.InsertBefore(retins, startInst);
worker.InsertBefore(retins,
worker.Create(OpCodes.Call, writeLineMR));
}
inst = inst.Next;
};
ComputeOffsets(meth.Body);
}
}
}
ShowTree(injectLibrary);// Shows correct jump location
injectLibrary.Write(testFile + ".MODDED.DLL");
injectLibrary = AssemblyDefinition.ReadAssembly(testFile +
".MODDED.DLL");
ShowTree(injectLibrary);// Shows NO jump location
}
}
>> The class to be modified in a Silverlight5 project:
public class BindingHelper
{
public static void OnUpdateSourceOnChangeChanged(DependencyObject
obj, DependencyPropertyChangedEventArgs e)
{
TextBox textBox = obj as TextBox;
if ((bool)e.NewValue)
{
textBox.TextChanged += (new
TextChangedEventHandler(BindingHelper.OnTextChanged));
textBox.DataContextChanged += (new
DependencyPropertyChangedEventHandler(BindingHelper.OnDataContextChanged));
if (!BindingHelper.GetIsValidatingOnTextChanged(textBox))
{
textBox.LostFocus += (new
RoutedEventHandler(BindingHelper.OnLostFocus));
textBox.GotFocus += (new
RoutedEventHandler(BindingHelper.OnGotFocus));
return;
}
}
else
{
textBox.TextChanged -= (new
TextChangedEventHandler(BindingHelper.OnTextChanged));
textBox.DataContextChanged -= (new
DependencyPropertyChangedEventHandler(BindingHelper.OnDataContextChanged));
if (!BindingHelper.GetIsValidatingOnTextChanged(textBox))
{
textBox.LostFocus -= (new
RoutedEventHandler(BindingHelper.OnLostFocus));
textBox.GotFocus -= (new
RoutedEventHandler(BindingHelper.OnGotFocus));
}
}
}
private static void OnTextChanged(object sender,
TextChangedEventArgs evtargs)
{
}
private static void OnGotFocus(object sender, RoutedEventArgs e)
{
}
private static void OnLostFocus(object sender, RoutedEventArgs e)
{
}
private static void OnDataContextChanged(object sender,
DependencyPropertyChangedEventArgs e)
{
}
private static bool GetIsValidatingOnTextChanged(TextBox textBox)
{
return true;
}
private static bool GetIsBindingHelperEnabled(TextBox textBox)
{
return true;
}
}
--
--
mono-cecil