// Scan the object code to find the first argument to ProtoMember for a given CAG private static int getProtoMemberArgument(CustomAttributeData att, long protoMemberCtor) { // Disassemble the CAG var code = asm.Disassemble(att.GetMethodBody(), (long)att.VirtualAddress.Start); var insIndex = -1; var disp = 0; // Step forwards through each instruction while (++insIndex < code.Length && disp == 0) { var ins = code[insIndex]; // Look for JMP and CALL instructions to the ProtoMember constructor if ((ins.Id == X86InstructionId.X86_INS_JMP || ins.Id == X86InstructionId.X86_INS_CALL) && ins.Details.Operands[0].Immediate == protoMemberCtor) { // Now step backwards looking for the most recent LEA EDX instruction while (--insIndex >= 0 && disp == 0) { ins = code[insIndex]; if (ins.Id == X86InstructionId.X86_INS_LEA && ins.Details.ExplicitlyWrittenRegisters[0].Id == X86RegisterId.X86_REG_EDX) { // The instruction is LEA EDX, [R8 + disp] // We know that R8 is zero so the displacement is the field number disp = (int)ins.Details.Displacement; } } if (insIndex == -1) { throw new InvalidOperationException("Unable to determine ProtoMember field number"); } } } return(disp); }