Skip to content

Commit 03122bf

Browse files
authored
Merge 2130d32 into 746d0c0
2 parents 746d0c0 + 2130d32 commit 03122bf

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

Confuser.Core/DnlibUtils.cs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,5 +515,96 @@ public static bool IsArrayAccessors(this IMethod method) {
515515
}
516516
return false;
517517
}
518+
519+
/// <summary>
520+
/// Merges a specified call instruction into the body.
521+
/// </summary>
522+
/// <param name="targetBody">The target body</param>
523+
/// <param name="callInstruction">The instruction to merge in</param>
524+
public static void MergeCall(this CilBody targetBody, Instruction callInstruction) {
525+
if (!(callInstruction.Operand is MethodDef methodToMerge))
526+
throw new ArgumentException("Call instruction has invalid operand");
527+
if (!methodToMerge.HasBody)
528+
throw new Exception("Method to merge has no body!");
529+
530+
var localParams = methodToMerge.Parameters.ToDictionary(param => param.Index, param => new Local(param.Type));
531+
var localMap = methodToMerge.Body.Variables.ToDictionary(local => local, local => new Local(local.Type));
532+
foreach (var local in localParams)
533+
targetBody.Variables.Add(local.Value);
534+
foreach (var local in localMap)
535+
targetBody.Variables.Add(local.Value);
536+
537+
// Nop the call
538+
int index = targetBody.Instructions.IndexOf(callInstruction);
539+
targetBody.Instructions[index++].OpCode = OpCodes.Nop;
540+
var afterIndex = targetBody.Instructions[index];
541+
542+
// Find Exception handler index
543+
int exIndex = 0;
544+
foreach (var ex in targetBody.ExceptionHandlers) {
545+
if (targetBody.Instructions.IndexOf(ex.TryStart) < index)
546+
exIndex = targetBody.ExceptionHandlers.IndexOf(ex);
547+
}
548+
549+
// setup parameter locals
550+
foreach (var paramLocal in localParams.Reverse()) {
551+
targetBody.Instructions.Insert(index++, new Instruction(OpCodes.Stloc, paramLocal.Value));
552+
}
553+
554+
var instrMap = new Dictionary<Instruction, Instruction>();
555+
var newInstrs = new List<Instruction>();
556+
557+
// Transfer instructions to list
558+
foreach (var instr in methodToMerge.Body.Instructions) {
559+
Instruction newInstr;
560+
if (instr.OpCode == OpCodes.Ret) {
561+
newInstr = new Instruction(OpCodes.Br, afterIndex);
562+
}
563+
else if (instr.IsLdarg()) {
564+
localParams.TryGetValue(instr.GetParameterIndex(), out var lc);
565+
newInstr = new Instruction(OpCodes.Ldloc, lc);
566+
}
567+
else if (instr.IsStarg()) {
568+
localParams.TryGetValue(instr.GetParameterIndex(), out var lc);
569+
newInstr = new Instruction(OpCodes.Stloc, lc);
570+
}
571+
else if (instr.IsLdloc()) {
572+
localMap.TryGetValue(instr.GetLocal(methodToMerge.Body.Variables), out var lc);
573+
newInstr = new Instruction(OpCodes.Ldloc, lc);
574+
}
575+
else if (instr.IsStloc()) {
576+
localMap.TryGetValue(instr.GetLocal(methodToMerge.Body.Variables), out var lc);
577+
newInstr = new Instruction(OpCodes.Stloc, lc);
578+
}
579+
else {
580+
newInstr = new Instruction(instr.OpCode, instr.Operand);
581+
}
582+
583+
newInstrs.Add(newInstr);
584+
instrMap[instr] = newInstr;
585+
}
586+
587+
// Fix branch targets & add instructions
588+
foreach (var instr in newInstrs) {
589+
if (instr.Operand != null && instr.Operand is Instruction instrOp && instrMap.ContainsKey(instrOp))
590+
instr.Operand = instrMap[instrOp];
591+
else if (instr.Operand is Instruction[] instructionArrayOp)
592+
instr.Operand = instructionArrayOp.Select(target => instrMap[target]).ToArray();
593+
594+
targetBody.Instructions.Insert(index++, instr);
595+
}
596+
597+
// Add Exception Handlers
598+
foreach (var eh in methodToMerge.Body.ExceptionHandlers) {
599+
targetBody.ExceptionHandlers.Insert(++exIndex, new ExceptionHandler(eh.HandlerType) {
600+
CatchType = eh.CatchType,
601+
TryStart = instrMap[eh.TryStart],
602+
TryEnd = instrMap[eh.TryEnd],
603+
HandlerStart = instrMap[eh.HandlerStart],
604+
HandlerEnd = instrMap[eh.HandlerEnd],
605+
FilterStart = eh.FilterStart == null ? null : instrMap[eh.FilterStart]
606+
});
607+
}
608+
}
518609
}
519610
}

0 commit comments

Comments
 (0)