В исправлении C# Harmony. как сравнить метки в CodeInstruction.labels с известными значениями меток
Итак, у меня есть такой поток IL-кода:
IL_0047: ldarg.0
IL_0048: ldc.i4.m1
IL_0049: stfld int32 classname/innerclassname::'<>1__state'
IL_004e: ldstr ""
IL_0053: call void classname::set_aProperty(string)
IL_0058: ldstr ""
IL_005d: call void classname::set_aProperty(string)
IL_0062: call int32 classname::get_aProperty()
IL_0067: ldc.i4.8
IL_0068: ble.s IL_0076
Я хочу заменить IL_004e переходом на IL_0067 (например). Класс System.Reflection.Emit.Label непрозрачен. Вы можете сравнить равенство. Но невозможно указать метку, с которой вы хотите ее сравнить, если вы еще не нашли метку посредством отражения. Итак, хотя я вижу, что ярлык существует, я понятия не имею, что это за ярлык. Label.ToString() просто возвращает «System.Reflection.Emit.Label». Есть ли способ создать ярлык:
if (instruction.labels.Contains(x => x == Label.FromString("IL_0067")))
или какой-то аналогичный метод расширения?
1 ответ
Судя по ответам на этот вопрос , метки — это абстракция для удобства; в байт-коде ассемблера операндом перехода является смещение относительно следующей инструкции. Насколько мне известно, не существует метода создания экземпляра System.Reflection.Emit.Label из имен меток, созданных декомпиляторами.
Однако вы можете ввестиILGenerator
в ваш транспилятор, который вы можете использовать для создания новой метки с помощью ILGenerator.DefineLabel. Вы можете использовать эту метку как операнд перехода и добавить ее в.labels
поле инструкции, к которой вы хотите перейти. Вы можете найти эту целевую инструкцию, просматривая некоторый контекст, например, первую инструкцию послеcall
кclassname.get_aProperty
.
Для получения дополнительной информации вы можете проверить документацию Harmony: Transpiler — CodeInstruction .